T09 · Insecure Skill Coding Practices
- Location
scripts/monitor_dividend_premium.py:21- Finding
Shell Command Injection in Telegram Alert Delivery
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a coherent market-data tracker, but it has under-disclosed external alerting and unsafe command execution patterns that need review before installation.
Review before installing. Do not configure TELEGRAM_BOT_TOKEN or cron until the Telegram chat ID is user-configurable, os.system curl calls are replaced with safe HTTP calls, and output paths are moved to a user-selected or skill-owned directory. Expect the skill to download Chinese market data and overwrite CSV/Excel report files when run.
scripts/monitor_dividend_premium.py:21Shell Command Injection in Telegram Alert Delivery
scripts/update_dividend_premium.py:19Hard-Coded Writes Outside the Skill Directory
scripts/update_dividend_premium.py:24Predictable Shared Temporary File Enables Symlink and Race Attacks
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
�息率溢价是否低于3%
3. 满足条件时发送Telegram通知
"""
import xlrd
import csv
import subprocess
import re
import os
from datetime import datetime, timedelta
from pathlib import Path
# 配置
DATA_DIR = "/Users/liyi/.openclaw/workspace"
CSV_FILE = os.path.join(DATA_DIR, "股息率溢价跟踪.csv")
EXCEL_FILE = os.path.join(DATA_DIR, "股息率溢价跟踪.xlsx")
TELEGRAM_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN", "")
TELEGRAM_CHAT_ID = "505395883"
def send_telegram(message):
"""发送Telegram消息"""
if not TELEGRAM_TOKEN:
print("未配置Telegram Bot Token")
return False
cmd = f"""curl -s -X POST https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage \
-d chat_id={TELEGRAM_CHAT_ID} \
-d text="{message}" \
-d parse_mode=HTML"""
os.system(cmd)
return True
def download_dividend_rate(date_str):
"""下载股息率"""
url = "https://oss-ch.csindex.com.cn/static/html/csindex/public/uploads/file/autofi
The declared purpose focuses on tracking and calculating a market metric, but the implementation apparently also performs outbound network access and sends Telegram notifications using a bot token, including to a hardcoded chat target. That mismatch is dangerous because hidden or under-disclosed behaviors can exfiltrate data, use secrets unexpectedly, or trigger external actions that users did not knowingly authorize; the hardcoded-recipient aspect makes the alerting path especially sensitive.
The script builds a shell command with untrusted data and executes it via os.system. The Telegram token comes from an environment variable and the message text is interpolated directly into the shell command, so shell metacharacters in either value could trigger command injection and arbitrary command execution under the script's privileges.
-d text="{message}" \
-d parse_mode=HTML"""
os.system(cmd)
return True
def download_dividend_rate(date_str):
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
url = "https://oss-ch.csindex.com.cn/static/html/csindex/public/uploads/file/autofile/indicator/H30269indicator.xls"
local_file = "/tmp/H30269indicator.xls"
os.system(f"curl -s -o {local_file} '{url}'")
try:
book = xlrd.open_workbook(local_file)
The script invokes a shell via os.system to run curl, which is riskier than necessary because shell execution expands the attack surface and can become command injection if any interpolated value later becomes user-controlled. In this file the arguments are currently hard-coded, so this is not immediately critical, but using a shell for network retrieval in a data-tracking skill is still an unsafe pattern.
url = "https://oss-ch.csindex.com.cn/static/html/csindex/public/uploads/file/autofile/indicator/H30269indicator.xls"
local_file = "/tmp/H30269indicator.xls"
os.system(f"curl -s -o {local_file} '{url}'")
try:
book = xlrd.open_workbook(local_file)
The skill advertises executable behavior involving shell commands, environment-variable access, and file read/write capabilities, but does not declare any explicit tool scope or permissions boundaries. This increases the risk that an agent or reviewer will underestimate the skill's operational reach, enabling unintended command execution, filesystem modification, or secret use without clear consent controls.
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.
crontab -e
# Add line:
0 17 * * * cd /path/to/skill && python3 scripts/update_dividend_premium.py --update
The script's natural-language interface and data retrieval are fixed to Chinese, including Chinese-only messaging and the locale parameter 'cn_ZH' in the bond yield request. There is no indication that this locale restriction is optional, user-selected, or justified as a region-specific tool.
The manifest describes the skill as tracking dividend yield, 10-year bond yield, and calculating the premium for investment decisions. This code also sends outbound Telegram messages, which is an extra operational behavior not reflected in the stated description.
This code transmits monitoring messages to Telegram using a bot token and chat ID, which is a network operation sending potentially sensitive user/system-derived data to a third party. Although the file header says notifications are sent, the code itself provides no confirmation prompt or explicit user-facing disclosure at the point of transmission beyond an internal docstring.
The hardcoded Telegram API endpoint confirms third-party data transmission. In this skill's context, that transmission is intentional for alerts, but any external egress increases privacy and governance risk, especially in agent environments where users may not expect network exfiltration.
print("未配置Telegram Bot Token")
return False
cmd = f"""curl -s -X POST https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage \
-d chat_id={TELEGRAM_CHAT_ID} \
-d text="{message}" \
-d parse_mode=HTML"""
The hardcoded Telegram API endpoint confirms third-party data transmission. In this skill's context, that transmission is intentional for alerts, but any external egress increases privacy and governance risk, especially in agent environments where users may not expect network exfiltration.
print("未配置Telegram Bot Token")
return False
cmd = f"""curl -s -X POST https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage \
-d chat_id={TELEGRAM_CHAT_ID} \
-d text="{message}" \
-d parse_mode=HTML"""
A credential-derived environment value flows into a shell command that is executed. If the TELEGRAM_BOT_TOKEN environment variable is attacker-controlled or malformed, it can break command structure and execute arbitrary commands; combining credential handling with shell construction amplifies the risk.
-d text="{message}" \
-d parse_mode=HTML"""
os.system(cmd)
return True
def download_dividend_rate(date_str):
The module-level documentation says to check whether dividend premium is below 3%, and the run_check comment at L131 also says '检查溢价低于3%'. However, check_premium_low actually triggers only when the premium is below 1.0, creating a direct contradiction between documentation/comments and code behavior.
The skill executes external commands to fetch remote content even though its stated purpose is simple data collection and calculation. That capability is broader than necessary and increases risk through dependency on shell tools, PATH resolution, and less controlled handling of remote data, especially in an automation context that will run unattended.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def get_bond_yield(date_str):
"""从财政部官网获取10年期国债收益率"""
result = subprocess.run(
['curl', '-s', 'https://yield.chinabond.com.cn/cbweb-czb-web/czb/moreInfo?locale=cn_ZH&nameType=1'],
capture_output=True, text=True
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def get_bond_yield(date_str):
"""从财政部官网获取10年期国债收益率"""
result = subprocess.run(
['curl', '-s', 'https://yield.chinabond.com.cn/cbweb-czb-web/czb/moreInfo?locale=cn_ZH&nameType=1'],
capture_output=True, text=True
)
The script writes updated data to the configured CSV file and regenerates the Excel workbook, which can overwrite existing local files. Although there are status prints, there is no explicit warning or confirmation that running the script will modify files under the user's workspace.
The update flow fetches data from external URLs and overwrites the local CSV file at a fixed path, which are network and file-write operations. While these actions are part of the script's purpose, there is no explicit warning in the code comments or user-facing messaging that running the default path performs both remote fetches and local data modification.
The request URL includes locale=cn_ZH, which forces a specific locale in the fetched content. This is a natural-language/locale policy concern because the script does not expose a user option or explain that it is intentionally restricted to Chinese-language data.
The stated purpose focuses on monitoring dividend yield, 10-year bond yield, and calculating the premium for investment decisions. This script goes beyond that by producing a formatted Excel artifact with visualization, which is an additional reporting/output feature not reflected in the description.
No suspicious patterns detected.