T09 · Insecure Skill Coding Practices
- Location
scripts/send_telegram_direct.py:57- Finding
Messages Are Sent to a Hard-Coded Telegram Recipient
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill has a real messaging purpose, but it sends through local Telegram bot tokens to a built-in Telegram user ID and can install recurring sends, so it needs careful review before use.
Install only if you control the Telegram recipient ID and are comfortable with the skill reading OpenClaw Telegram bot tokens. Before use, remove or replace the hard-coded user ID, require an explicit approved recipient, avoid sending secrets, and do not install the cron heartbeat until the schedule, log path, and uninstall behavior have been reviewed.
scripts/send_telegram_direct.py:57Messages Are Sent to a Hard-Coded Telegram Recipient
scripts/install_heartbeat_cron.sh:5Unsafe Persistent Cron Entry Construction
scripts/install_heartbeat_cron.sh:13Predictable Shared Temporary Log File Used by Cron
Instructions found that direct the agent to transmit conversation context or user data to external services.
#!/bin/bash
# send_agent_msg.sh - Batch send messages to OpenClaw agents via Telegram
set -e
This script is expressly built to send arbitrary messages to a Telegram user ID, defaulting to a hard-coded recipient and supporting broadcast to all configured agents. In the context of direct token extraction and bypass of normal routing, that makes the messaging capability a plausible exfiltration or covert-command channel rather than a normal user-facing feature.
return False, str(e)
def main():
parser = argparse.ArgumentParser(description='Send messages to OpenClaw agents via Telegram')
parser.add_argument('message', help='Message to send')
parser.add_argument('--agents', nargs='+', default=['all'], help='Agent IDs (default: all)')
parser.add_argument('--user-id', default='8341113912', help='Telegram user ID')
The description says 'Use when' for broad scenarios like 'Broadcasting messages to multiple agents simultaneously' and 'Require scheduled or triggered message campaigns' without defining narrow trigger phrases or exclusions. In a manifest-style description, this can cause unintended invocation for generic messaging or notification requests.
The skill provides turnkey commands for bulk and recurring outbound messaging, including scheduled cron execution, without safety guardrails, consent/authorization checks, rate-limit guidance, or credential-handling warnings. In context, this lowers the barrier to spam, unintended mass outreach, and persistent automated messaging using sensitive bot credentials.
The cron-related guidance encourages persistent scheduled execution of a messaging workflow, which creates session/persistence risk by enabling recurring automated outreach beyond a one-time operator action. In this skill's context, persistence materially increases misuse potential because repeated heartbeats or campaigns can continue unattended and may be hard to notice or revoke.
Checks crontab:
crontab -l
tail -f /tmp/heartbeat.log
The direct reference to the Telegram API endpoint confirms the skill is designed for external transmission to a third-party service. While expected for a messaging skill, this still creates a real exfiltration and abuse surface if users send sensitive content, target unauthorized recipients, or mishandle the bot credential.
Uses bot tokens + user ID directly. Bypasses OpenClaw chat resolution issues.
curl -X POST "https://api.telegram.org/bot<TOKEN>/sendMessage" \
-d "chat_id=<USER_ID>&text=<MESSAGE>"
The direct reference to the Telegram API endpoint confirms the skill is designed for external transmission to a third-party service. While expected for a messaging skill, this still creates a real exfiltration and abuse surface if users send sensitive content, target unauthorized recipients, or mishandle the bot credential.
Uses bot tokens + user ID directly. Bypasses OpenClaw chat resolution issues.
curl -X POST "https://api.telegram.org/bot<TOKEN>/sendMessage" \
-d "chat_id=<USER_ID>&text=<MESSAGE>"
The script states that the output confirms all agents received the message, but it never verifies message delivery or checks for acknowledgments. In an operational setting, this can create false assurance that agents are reachable or responsive, which may delay incident response or hide communication failures.
This script installs a recurring cron entry, which is a persistence mechanism by design. Even though the apparent purpose is administrative and not overtly malicious, any code that establishes scheduled execution creates ongoing execution on the host and can be abused if the referenced heartbeat script is modified or if the installer is run without adequate review.
CRON_JOB="$CRON_INTERVAL * * * * bash $HEARTBEAT_SCRIPT > /tmp/heartbeat.log 2>&1"
# Check if already exists
if crontab -l 2>/dev/null | grep -q "heartbeat_check.sh"; then
echo "⚠️ Cron job already exists!"
echo ""
echo "Current crontab:"
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
echo "⚠️ Cron job already exists!"
echo ""
echo "Current crontab:"
crontab -l | grep heartbeat
echo ""
read -p "Remove and reinstall? (y/n) " -n 1 -r
echo
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
echo "⚠️ Cron job already exists!"
echo ""
echo "Current crontab:"
crontab -l | grep heartbeat
echo ""
read -p "Remove and reinstall? (y/n) " -n 1 -r
echo
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
echo "⚠️ Cron job already exists!"
echo ""
echo "Current crontab:"
crontab -l | grep heartbeat
echo ""
read -p "Remove and reinstall? (y/n) " -n 1 -r
echo
This line appends a new cron job to the current user's crontab, establishing recurring execution and therefore persistence. In the skill context, that is the explicit function of the script, which makes the finding more credible, and it becomes dangerous if users do not fully understand that a background task will continue running indefinitely.
fi
# Install new job
(crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab -
echo "✅ Installed cron job!"
echo ""
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
echo " /tmp/heartbeat.log"
echo ""
echo "🛑 To remove:"
echo " crontab -e # then delete the heartbeat line"
echo ""
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="/data/.openclaw/openclaw.json"
TELEGRAM_API="https://api.telegram.org/bot"
# Parse arguments
MESSAGE=""
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="/data/.openclaw/openclaw.json"
TELEGRAM_API="https://api.telegram.org/bot"
# Parse arguments
MESSAGE=""
The script extracts account IDs and Telegram bot tokens from the local config file, which constitutes access to sensitive credentials, but there is no comment, docstring, or user-facing disclosure explaining that credential material will be read. Under the code-file criteria, sensitive credential access should not be silent when no markdown warning is available.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
EMOJI=$(jq -r ".agents.list[] | select(.id==\"$agent\") | .identity.emoji // \"\"" "$CONFIG_FILE")
# Send via Telegram API
RESPONSE=$(curl -s -X POST "${TELEGRAM_API}${BOT_TOKEN}/sendMessage" \
-d "chat_id=$USER_ID" \
-d "text=$EMOJI $AGENT_NAME: $FINAL_MESSAGE")
The script performs an outbound HTTP request to the Telegram API and transmits the composed message, agent name, emoji, and target chat ID, but the only nearby comment says 'Send via Telegram API' and there is no user-facing warning about external data transmission. For code files, network calls that transmit user or system data should have visible disclosure unless the warning is provided elsewhere in markdown, which is not present in this file.
The script reads the OpenClaw configuration, locates Telegram account bindings, and extracts bot tokens in order to send messages outside the normal platform flow. Accessing and using credentials directly is sensitive behavior, and here it is paired with a stated goal of bypassing the normal chat-resolution mechanism, which materially increases the risk of unauthorized messaging and abuse of stored secrets.
The code pulls Telegram bot tokens from local configuration and immediately uses them to perform outbound HTTP requests, without any warning, consent flow, or trust boundary documentation. Even if the intent is operational convenience, this creates a stealthy credential-use and external-transmission path that can be repurposed for unauthorized communication or data exfiltration.
The default message text is hard-coded in French: "Tout le monde là? Envoie ✅ si tu reçois". This imposes a specific language on users/agents without any opt-in, fallback, or documented region-specific justification, which matches the language/locale policy violation category.
The docstring claims the tool is for agent messaging, but it explicitly 'bypasses OpenClaw chat resolution' and sends directly to an arbitrary Telegram user ID. That mismatch is dangerous because it conceals the real security-sensitive behavior and can mislead reviewers or operators about the destination and control boundaries of outbound messages.
No suspicious patterns detected.