T08 · Insecure Dependencies
- Location
setup.sh:15- Finding
Unpinned dependencies are installed into the host Python environment
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill appears to provide NEPSE stock analysis, but its installer handles Telegram credentials unsafely and can send watchlist or alert information to Telegram.
Review this skill before installing. Use a virtual environment with pinned dependencies instead of the provided pip command, do not run setup with elevated privileges, and do not paste a Telegram bot token into the installer unless you are comfortable with it being displayed. If enabling Telegram alerts, use a narrowly scoped bot token, store it in a dedicated secret mechanism rather than ~/.bashrc, and assume watchlist symbols, prices, and alert thresholds may be sent to Telegram.
setup.sh:15Unpinned dependencies are installed into the host Python environment
setup.sh:38Telegram bot credentials are entered visibly and printed in plaintext
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
��──────────────────────────────────────────────────────────────
SKILL_DIR = Path(__file__).parent.parent
DATA_DIR = SKILL_DIR / "data"
DATA_DIR.mkdir(exist_ok=True)
WATCHLIST_FILE = DATA_DIR / "watchlist.json"
ALERTS_FILE = DATA_DIR / "alerts.json"
TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "")
HEADERS = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120.0 Safari/537.36"
}
# ── helpers ─────────────────────────────────────────────────────────────────
def load_json(path: Path, default):
if path.exists():
try:
return json.loads(path.read_text())
except Exception:
return default
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
��──────────────────────────────────────────────────────────────
SKILL_DIR = Path(__file__).parent.parent
DATA_DIR = SKILL_DIR / "data"
DATA_DIR.mkdir(exist_ok=True)
WATCHLIST_FILE = DATA_DIR / "watchlist.json"
ALERTS_FILE = DATA_DIR / "alerts.json"
TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "")
HEADERS = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120.0 Safari/537.36"
}
# ── helpers ─────────────────────────────────────────────────────────────────
def load_json(path: Path, default):
if path.exists():
try:
return json.loads(path.read_text())
except Exception:
return default
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
return False
try:
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
resp = requests.post(url, json={
"chat_id": TELEGRAM_CHAT_ID,
"text": message,
"parse_mode": "Markdown"
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
symbol = symbol.upper()
url = f"https://merolagani.com/CompanyDetail.aspx?symbol={symbol}"
try:
resp = requests.get(url, headers=HEADERS, timeout=15)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
symbol = symbol.upper()
url = f"https://merolagani.com/CompanyDetail.aspx?symbol={symbol}"
try:
resp = requests.get(url, headers=HEADERS, timeout=15)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
symbol = symbol.upper()
url = f"https://merolagani.com/CompanyDetail.aspx?symbol={symbol}"
try:
resp = requests.get(url, headers=HEADERS, timeout=15)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
return False
try:
r = requests.post(
f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage",
json={"chat_id": TELEGRAM_CHAT_ID, "text": msg, "parse_mode": "Markdown"},
timeout=10
The skill documentation instructs runtime dependency installation and Telegram configuration, which are materially different from passive stock analysis. This broadens the effective attack surface to package management, secret collection, and outbound messaging without transparent declaration, increasing the risk of unsafe execution in a financial-assistant context.
The skill documentation instructs runtime dependency installation and Telegram configuration, which are materially different from passive stock analysis. This broadens the effective attack surface to package management, secret collection, and outbound messaging without transparent declaration, increasing the risk of unsafe execution in a financial-assistant context.
The skill invokes a local Python script, performs dependency installation, manages watchlists/alerts, and documents outbound alerting, yet it declares no explicit tool scope or permissions. This creates an over-privileged, opaque execution model where shell, filesystem, environment, and network access may be used without user-visible restriction or review.
The manifest says to use the skill for 'anything related to Nepal stock market' and includes generic phrases like 'analyze X' and 'price of X'. In a markdown/manifest context, these triggers are broad enough to cause unintended invocation because they lack clear scope boundaries or negative examples.
Automatic Telegram alert sending is an outbound-notification capability beyond simple local analysis/watchlist functionality, and it is introduced without clear security boundaries. Such messaging can transmit user interests, portfolio/watchlist symbols, or derived trading signals to a third-party service, creating privacy and exfiltration risk.
The cron instructions describe automatic Telegram alerts without warning that user-related data will be transmitted externally. Lack of disclosure around outbound notifications can lead to silent data sharing, especially risky in a finance skill where watchlists and alert thresholds may reflect sensitive investment intent.
The skill reads Telegram bot credentials from the environment and can transmit watchlist and alert information to an external messaging service. In an agent-skill context, this expands data access and outbound communication beyond core local analysis, creating privacy and policy risk if users are not clearly informed or if the skill is enabled in broader environments with sensitive configuration present.
The code performs external message delivery to Telegram in addition to data retrieval and analysis. While alerts are related to market monitoring, agent skills that send data off-platform are more dangerous because they introduce an exfiltration channel and behavior that may not be expected during routine analysis requests.
The hardcoded Telegram endpoint indicates the skill is designed to send data to an external third-party service. That is not inherently malicious, but it increases risk in this context because a stock-analysis skill now has built-in off-platform communications using environment-provided credentials.
if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
return False
try:
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
resp = requests.post(url, json={
"chat_id": TELEGRAM_CHAT_ID,
"text": message,
This is a real external transmission to Telegram containing message text and chat metadata. In isolation it is normal API use, but in a skill environment it matters because it creates an outbound channel that can leak user-derived market interests or future modifications could piggyback on the same path.
return False
try:
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
resp = requests.post(url, json={
"chat_id": TELEGRAM_CHAT_ID,
"text": message,
"parse_mode": "Markdown"
The cron-check workflow sends watchlist contents and triggered alert information to Telegram without any user-facing warning, consent flow, or transparency at send time. Even if the data seems low sensitivity, portfolio interests and monitoring rules can reveal trading intent and should not be silently forwarded to third parties.
The file is named rsi_alert.py, yet the module docstring explicitly documents 'Intraday Seller Detection' with triggers based on price dropping from open and volume exceeding a 10-day average. The implemented logic in check_intraday() matches seller-detection criteria and does not calculate or use RSI, so the documentation/intent signaled by the file identity diverges from the actual behavior.
The manifest describes a NEPSE analyst skill for stock analysis, prices, signals, alerts, screening, and portfolio tracking, but does not state any need to access environment-held bot credentials or integrate with an external messaging platform. This code reads TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID and uses them to send messages to Telegram, which is an additional notification capability beyond the stated analyst role.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
return False
try:
r = requests.post(
f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage",
json={"chat_id": TELEGRAM_CHAT_ID, "text": msg, "parse_mode": "Markdown"},
timeout=10
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
return False
try:
r = requests.post(
f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage",
json={"chat_id": TELEGRAM_CHAT_ID, "text": msg, "parse_mode": "Markdown"},
timeout=10
)
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.
pip3 install requests beautifulsoup4 numpy --break-system-packages --quiet
echo " ✓ Python deps installed"
# 2. create skill directory in openclaw workspace
echo "[2/4] Creating skill directory at ${TARGET_DIR}..."
mkdir -p "${TARGET_DIR}/scripts"
mkdir -p "${TARGET_DIR}/data"
The script prompts for a Telegram bot token and chat ID, then echoes both secrets back to the terminal and recommends storing them in shell startup files. This increases the chance of accidental exposure through terminal logs, screen sharing, shell history-adjacent workflows, backups, or overly broad file permissions, especially because bot tokens are authenticators rather than mere identifiers.
The setup instructions explicitly advise persisting TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID in ~/.bashrc, causing credentials to be loaded into every future shell session. Persisting secrets in a general-purpose startup file broadens exposure to local users, backup systems, dotfile syncing, accidental disclosure, and subprocess environment leakage.
echo ' }'
echo ' }'
echo ""
echo " Or export them in your shell: add to ~/.bashrc:"
echo " export TELEGRAM_BOT_TOKEN=\"${BOT_TOKEN}\""
echo " export TELEGRAM_CHAT_ID=\"${CHAT_ID}\""
fi
No suspicious patterns detected.