T01 · Skill Instruction Hijacking
- Location
scripts/imap_watcher.py:386- Finding
Attacker-Controlled Email Metadata Is Embedded Directly into Agent Instructions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This email watcher is mostly transparent about what it does, but it installs a persistent system service with mailbox and agent access and has supply-chain and prompt-injection risks that merit careful review.
Install only if you are comfortable with a persistent email-monitoring service that stores mailbox credentials and an OpenClaw gateway token locally. Prefer setting an explicit channel and target, keep auto-reply disabled or approval-only, review the systemd service before enabling it, and avoid the automatic Himalaya download unless you can verify the binary version and checksum yourself.
scripts/imap_watcher.py:386Attacker-Controlled Email Metadata Is Embedded Directly into Agent Instructions
scripts/imap_watcher.py:217Email Notifications May Be Delivered to an Unrelated OpenClaw Session
scripts/imap_watcher.py:351OpenClaw Gateway Token Is Passed Through Process Command-Line Arguments
scripts/setup.py:148Mutable Himalaya Release Is Downloaded and Installed as a System Executable Without Integrity Verification
scripts/setup.py:179Python Dependency Is Installed Without Version or Hash Pinning
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
#!/usr/bin/env python3
"""Unregister beemail bot commands from Telegram.
Standalone script called by uninstall.sh to cleanly remove
/beemail* commands from the Telegram bot menu.
"""
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
### Changes
- **`read_openclaw_gateway_token()`** in `setup.py`: reads `gateway.auth.token` from the OpenClaw config at install time (as root), trying `$OPENCLAW_HOME`, `/root/.openclaw/openclaw.json`, and `~/.openclaw/openclaw.json`
- **`validate_config()`**: automatically reads and stores the gateway token as `openclaw_token` in `watcher.conf` (chmod 600) during install. Shows warning if not found with instructions for manual fallback.
- **`notify_openclaw()`** in `imap_watcher.py`: passes `--token <openclaw_token>` to every `openclaw agent --deliver` call. Logs `[SECURITY] WARNING` if token is missing.
- **`verify()` step [5/5]**: calls `verify_openclaw_deliver()` — a real `openclaw agent --deliver` test with the stored token. Install fails if delivery fails, ensuring the issue is caught at install time not at runtime.
- **`CONFIG_MIGRATIONS`**: added `openclaw_token` entry (v1.5.2) so existing installs get prompted to add the token via `--reconfigure`
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
### Changes
- **`read_openclaw_gateway_token()`** in `setup.py`: reads `gateway.auth.token` from the OpenClaw config at install time (as root), trying `$OPENCLAW_HOME`, `/root/.openclaw/openclaw.json`, and `~/.openclaw/openclaw.json`
- **`validate_config()`**: automatically reads and stores the gateway token as `openclaw_token` in `watcher.conf` (chmod 600) during install. Shows warning if not found with instructions for manual fallback.
- **`notify_openclaw()`** in `imap_watcher.py`: passes `--token <openclaw_token>` to every `openclaw agent --deliver` call. Logs `[SECURITY] WARNING` if token is missing.
- **`verify()` step [5/5]**: calls `verify_openclaw_deliver()` — a real `openclaw agent --deliver` test with the stored token. Install fails if delivery fails, ensuring the issue is caught at install time not at runtime.
- **`CONFIG_MIGRATIONS`**: added `openclaw_token` entry (v1.5.2) so existing installs get prompted to add the token via `--reconfigure`
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
### Changes
- **`read_openclaw_gateway_token()`** in `setup.py`: reads `gateway.auth.token` from the OpenClaw config at install time (as root), trying `$OPENCLAW_HOME`, `/root/.openclaw/openclaw.json`, and `~/.openclaw/openclaw.json`
- **`validate_config()`**: automatically reads and stores the gateway token as `openclaw_token` in `watcher.conf` (chmod 600) during install. Shows warning if not found with instructions for manual fallback.
- **`notify_openclaw()`** in `imap_watcher.py`: passes `--token <openclaw_token>` to every `openclaw agent --deliver` call. Logs `[SECURITY] WARNING` if token is missing.
- **`verify()` step [5/5]**: calls `verify_openclaw_deliver()` — a real `openclaw agent --deliver` test with the stored token. Install fails if delivery fails, ensuring the issue is caught at install time not at runtime.
- **`CONFIG_MIGRATIONS`**: added `openclaw_token` entry (v1.5.2) so existing installs get prompted to add the token via `--reconfigure`
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
### Changes
- **`read_openclaw_gateway_token()`** in `setup.py`: reads `gateway.auth.token` from the OpenClaw config at install time (as root), trying `$OPENCLAW_HOME`, `/root/.openclaw/openclaw.json`, and `~/.openclaw/openclaw.json`
- **`validate_config()`**: automatically reads and stores the gateway token as `openclaw_token` in `watcher.conf` (chmod 600) during install. Shows warning if not found with instructions for manual fallback.
- **`notify_openclaw()`** in `imap_watcher.py`: passes `--token <openclaw_token>` to every `openclaw agent --deliver` call. Logs `[SECURITY] WARNING` if token is missing.
- **`verify()` step [5/5]**: calls `verify_openclaw_deliver()` — a real `openclaw agent --deliver` test with the stored token. Install fails if delivery fails, ensuring the issue is caught at install time not at runtime.
- **`CONFIG_MIGRATIONS`**: added `openclaw_token` entry (v1.5.2) so existing installs get prompted to add the token via `--reconfigure`
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
### Changes
- **`read_openclaw_gateway_token()`** in `setup.py`: reads `gateway.auth.token` from the OpenClaw config at install time (as root), trying `$OPENCLAW_HOME`, `/root/.openclaw/openclaw.json`, and `~/.openclaw/openclaw.json`
- **`validate_config()`**: automatically reads and stores the gateway token as `openclaw_token` in `watcher.conf` (chmod 600) during install. Shows warning if not found with instructions for manual fallback.
- **`notify_openclaw()`** in `imap_watcher.py`: passes `--token <openclaw_token>` to every `openclaw agent --deliver` call. Logs `[SECURITY] WARNING` if token is missing.
- **`verify()` step [5/5]**: calls `verify_openclaw_deliver()` — a real `openclaw agent --deliver` test with the stored token. Install fails if delivery fails, ensuring the issue is caught at install time not at runtime.
- **`CONFIG_MIGRATIONS`**: added `openclaw_token` entry (v1.5.2) so existing installs get prompted to add the token via `--reconfigure`
The README describes triggering the agent on every newly arrived email with no clear scoping, sender restrictions, folder restrictions beyond a configurable IMAP folder, or content-based safety gates. In an agent context, broad activation on untrusted inbound email expands the attack surface for prompt injection, spam-triggered actions, data exposure, and unwanted autonomous behavior.
The README explicitly describes creating, enabling, and starting a persistent systemd service that monitors email continuously and can trigger agent actions over time. Persistent background execution increases the blast radius of any misconfiguration or compromise, especially when driven by untrusted inbound email and capable of restarting automatically.
| **Python venv** | Creates `/opt/imap-watcher/` with isolated Python environment |
| **pip install** | Installs `imapclient` inside the venv only (not system-wide) |
| **himalaya download** | Downloads binary from GitHub Releases to `/usr/local/bin/` (only if missing) |
| **systemd service** | Creates `/etc/systemd/system/imap-watcher.service`, enables and starts it |
| **Config file** | Writes `/opt/imap-watcher/watcher.conf` with chmod 600 (owner-only read/write) |
| **System user** | Creates `imap-watcher` system user — service runs as non-root |
| **Bot token read** | Reads `botToken` from `~/.openclaw/openclaw.json` to register Telegram menu commands |
The skill requires privileged system changes including writing to /etc/systemd/system, /usr/local/bin, /opt, /var/log, and creating a system user. In an agent-operated installation flow, this elevates risk because compromised setup logic, unsafe downloads, or prompt-influenced execution could yield persistent privileged changes to the host.
| **pip install** | Installs `imapclient` inside the venv only (not system-wide) |
| **himalaya download** | Downloads binary from GitHub Releases to `/usr/local/bin/` (only if missing) |
| **systemd service** | Creates `/etc/systemd/system/imap-watcher.service`, enables and starts it |
| **Config file** | Writes `/opt/imap-watcher/watcher.conf` with chmod 600 (owner-only read/write) |
| **System user** | Creates `imap-watcher` system user — service runs as non-root |
| **Bot token read** | Reads `botToken` from `~/.openclaw/openclaw.json` to register Telegram menu commands |
| **Log files** | Writes to `/var/log/imap-watcher.log` and systemd journal |
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
Validates IMAP + SMTP + Himalaya with your credentials. Nothing is installed.
### Stage 3: Install
Deploys the watcher as a systemd service. Automatically runs Stage 1 + 2 first.
### Stage 4: Verify (automatic)
Checks service is running, IMAP is connected, config is valid, agent is reachable.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
All config lives in /opt/imap-watcher/watcher.conf (JSON, chmod 600):
{
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
All config lives in /opt/imap-watcher/watcher.conf (JSON, chmod 600):
{
Allowing a custom per-account message that overrides normal agent behavior can cause the agent to include sensitive email contents, user data, or credentials in downstream notifications or replies. Because the trigger source is untrusted email, this customization can weaken safety boundaries and amplify prompt-injection or data-exfiltration risks.
The skill establishes a persistent background capability by design: it installs and manages an always-on email-watching service that triggers agent actions on new mail. Even though this persistence is disclosed and appears intended for functionality, it expands the attack surface because a compromised watcher, mailbox, or agent pipeline would have continuous execution and monitoring capability.
---
name: bee-push-email
description: Push email notifications via IMAP IDLE + Himalaya + OpenClaw agent. Detects new emails in real-time and triggers the agent to process and notify the user. Use when: setting up email push notifications, configuring IMAP watcher, installing bee-push-email system, testing email connectivity, checking system dependencies, viewing email-push config, troubleshooting IMAP IDLE watcher, or managing the imap-watcher systemd service. Also handles uninstall/cleanup of the bee-push-email system. Trigger on beemail commands: /beemail, /beemail_start, /beemail_stop, /beemail_status, /beemail_test, /beemail_reply, /beemail_reply_off, /beemail_reply_ask, /beemail_reply_on. Also: start watcher, stop watcher, watcher status, email push status, registrar comandos, comandos no aparecen, beemail no funciona en telegram.
emoji: 📧
requirements:
bins:
This line confirms installation of a systemd unit that is enabled, started, and restarted on boot, creating durable persistence on the host. In this skill's context that behavior is expected, but it is still security-relevant because it creates long-lived autonomous execution tied to incoming email, a potentially attacker-influenced input channel.
| **Python venv** | `/opt/imap-watcher/` | Isolated env, not system-wide |
| **pip package** | `imapclient` (inside venv only) | Not installed system-wide |
| **Watcher script** | `/opt/imap-watcher/imap_watcher.py` | Copied from skill directory |
| **systemd unit** | `/etc/systemd/system/imap-watcher.service` | Enabled + started, restarts on boot |
| **Config file** | `/opt/imap-watcher/watcher.conf` | chmod 600, owner imap-watcher only |
| **Log file** | `/var/log/imap-watcher.log` | chmod 640, owner imap-watcher |
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
| **Watcher script** | `/opt/imap-watcher/imap_watcher.py` | Copied from skill directory |
| **systemd unit** | `/etc/systemd/system/imap-watcher.service` | Enabled + started, restarts on boot |
| **Config file** | `/opt/imap-watcher/watcher.conf` | chmod 600, owner imap-watcher only |
| **Log file** | `/var/log/imap-watcher.log` | chmod 640, owner imap-watcher |
### External downloads (requires user awareness)
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
| **Watcher script** | `/opt/imap-watcher/imap_watcher.py` | Copied from skill directory |
| **systemd unit** | `/etc/systemd/system/imap-watcher.service` | Enabled + started, restarts on boot |
| **Config file** | `/opt/imap-watcher/watcher.conf` | chmod 600, owner imap-watcher only |
| **Log file** | `/var/log/imap-watcher.log` | chmod 640, owner imap-watcher |
### External downloads (requires user awareness)
The module description claims the watcher only processes and notifies about new mail, but the code can instruct the downstream agent to reply to senders and move emails. This mismatch is dangerous because operators may deploy it with an incomplete understanding of its capabilities, leading to unintended outbound communication or mailbox modification.
The module docstring describes the skill entirely in Spanish ('push real de emails nuevos', 'Mantiene conexion IMAP IDLE persistente'), which imposes a specific language in user-facing natural language without any opt-in or alternative. The policy for natural-language violations applies to all file types, including code comments and docstrings, when they communicate operational behavior.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
cmd.extend(['--channel', session['channel']])
if session.get('target'):
cmd.extend(['--to', session['target']])
subprocess.run(cmd, capture_output=True, text=True, timeout=30)
log.info("[SECURITY] Agent notified about missing config fields.")
except Exception as e:
log.warning(f"[SECURITY] Could not notify agent about missing fields: {e}")
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
preferred_channel = config.get('preferred_channel', 'telegram')
try:
cmd_result = subprocess.run(
['openclaw', 'sessions'],
capture_output=True,
text=True,
Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.
# Build a minimal himalaya config from watcher.conf
tmpdir = tempfile.mkdtemp(prefix='bee-meta-')
tmp_config = os.path.join(tmpdir, 'config.toml')
atexit.register(lambda: __import__('shutil').rmtree(tmpdir, ignore_errors=True))
try:
enc_type = 'tls' if config.get('ssl', True) else 'none'
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
for uid in sorted(uids):
try:
result = subprocess.run(
['himalaya', '-c', tmp_config, '-a', 'watcher',
'-f', folder, 'message', 'read', str(uid),
'--preview'],
The code automatically forwards sender and subject metadata from incoming emails into a natural-language message delivered to whatever active OpenClaw session is resolved. If session resolution is wrong, shared, stale, or points to another channel/user, sensitive email metadata can be disclosed outside the mailbox without explicit user consent; additionally, untrusted email text is embedded directly into agent-facing instructions, increasing prompt-injection risk downstream.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
try:
log.info(f"Triggering OpenClaw agent: {' '.join(cmd[:6])}...")
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
log.info(f"OpenClaw agent triggered. Exit code: {result.returncode}")
if result.stdout:
log.info(f"OpenClaw stdout: {result.stdout[:500]}")
No suspicious patterns detected.