T09 · Insecure Skill Coding Practices
- Location
turkish-news/SKILL.md:127- Finding
Unsafe manual serialization of externally controlled RSS fields
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly a disclosed Turkish briefing automation package, but it has enough scope and documentation mismatches around market tracking, dependencies, and recurring outbound delivery to require Review before installation.
Review before installing. Confirm you actually want recurring Telegram or Discord delivery, verify the target chat or channel and removal process, avoid sending sensitive summaries, and treat the BIST/crypto market tooling as inconsistent until the publisher fixes the docs and script naming. Use pinned dependencies in an isolated environment if you run the bundled scripts.
turkish-news/SKILL.md:127Unsafe manual serialization of externally controlled RSS fields
scripts/telegram_send.py:128Untrusted Telegram messages and captions are interpreted as HTML
scripts/telegram_send.py:22Unpinned requests dependency in the Telegram sender
scripts/bist100_prices.py:19Unpinned requests dependency in the cryptocurrency price script
scripts/turkish_brief_card.py:17Unpinned Pillow dependency in the briefing card generator
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
�━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Sabitler / Constants
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
TELEGRAM_API_BASE = "https://api.telegram.org/bot{token}"
# Varsayılan caption (resim gönderiminde)
DEFAULT_CAPTION = "🌅 Günlük Brifing — Hermes Agent 🇹🇷"
# Telegram API limitleri
MAX_CAPTION_LENGTH = 1024 # sendPhoto caption limiti
MAX_MESSAGE_LENGTH = 4096 # sendMessage metin limiti
MAX_PHOTO_SIZE = 10 * 1024 * 1024 # 10 MB foto limiti
# ANSI renkleri
class C:
RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
CYAN = "\033[96m"
DIM = "\033[2m"
BOLD = "\033[1m"
RESET = "\033[0m"
# ━━━━━━━━━━━━━━━━━━━━━�
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
try:
with open(path, "rb") as photo:
files = {"photo": (path.name, photo, "image/png")}
resp = requests.post(url, data=payload, files=files, timeout=30)
result = resp.json()
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
try:
resp = requests.post(url, json=payload, timeout=15)
result = resp.json()
if result.get("ok"):
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
"""
url = f"{TELEGRAM_API_BASE.format(token=token)}/getMe"
try:
resp = requests.get(url, timeout=10)
result = resp.json()
if result.get("ok"):
bot = result["result"]
The code’s primary purpose is materially different from the declared description. Although it is Turkish-localized in language and TRY currency formatting, the functional behavior is a crypto market tracker, not a BIST100 stock tracker. It fetches data from CoinGecko and supports coin selection, sorting, and JSON/table output for cryptocurrencies. The declared description also mentions Turkish news sources, daily brief automation, and a Turkish personality template, none of which appear in this code chunk. Therefore this is a clear description-behavior mismatch.
The declared description frames the skill as a Turkish locale pack focused on Turkish news, BIST100 tracking, daily brief automation, and Turkish personality templating. The supplied code does not fetch news, track stocks, generate briefs, or configure Turkish-language personality behavior. Instead, it is a Telegram delivery tool that posts images or text to a specified Telegram channel/chat and verifies bot connectivity using TELEGRAM_BOT_TOKEN and TELEGRAM_HOME_CHANNEL. While 'daily brief automation' could plausibly include distribution, Telegram broadcasting is a significant undeclared capability and appears to be the code's primary purpose here. Therefore the code materially differs from the declared description.
The declared description presents a broader Turkish locale skill pack with news sources, BIST100 tracking, daily brief automation, and a Turkish personality template. The supplied code chunk is much narrower: it is a local image generator that reads optional JSON input or uses demo data and outputs a formatted PNG briefing card. It performs no network access, no source retrieval, no live market/news tracking, no scheduling/automation, and no personality/template logic. While the card generator could be a supporting component of a daily briefing system, this chunk alone does not accurately represent the broader declared capabilities, so this is a mismatch.
The script materially diverges from the skill manifest by implementing a cryptocurrency tracker instead of the declared BIST100/Turkish stock-tracking capability. This kind of capability mismatch is dangerous because users, reviewers, or downstream agents may trust the manifest and invoke the script under false assumptions, causing unauthorized data flows, incorrect financial automation, or hidden expansion of the skill’s effective scope.
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).
---
name: turkish-daily-brief
version: 1.0.0
description: "Telegram veya Discord üzerinden otomatik günlük Türkçe brifing — haberler, piyasalar, hava durumu ve günün özeti. / Automated daily Turkish brief via Telegram or Discord — news, markets, weather, and day summary."
tags: [turkish, daily-brief, telegram, discord, automation, cronjob, morning-brief]
author: Hermes Agent Hackathon 2026
triggers:
- "günlük brifing", "sabah brifing", "daily brief"
- "her sabah haber gönder", "otomatik sabah özeti"
- "Telegram'dan brifing", "günlük rapor"
- user wants to schedule recurring Turkish news/market updates
---
# �
The sample code fetches remote content by invoking curl via terminal(), then pipes it into an inline Python script. Using external command execution for network retrieval in a skill materially increases the risk surface: it can enable command injection if inputs later become user-controlled, weakens sandbox assumptions, and normalizes a dangerous pattern in a context that only needs straightforward RSS fetching.
from hermes_tools import web_extract, terminal
import json
# Fetch RSS feeds via curl (faster than web_extract for XML)
sources = {
"Hürriyet": "https://www.hurriyet.com.tr/rss/anasayfa",
"NTV": "https://www.ntv.com.tr/son-dakika.rss",
The skill advertises capabilities that inherently require network, file, and possibly environment access, but it does not declare any explicit tool scope or permission boundaries. In an agent ecosystem, missing scope declarations increase the chance of over-broad tool use, hidden side effects, or execution under default privileges that exceed what users expect.
The skill prominently promotes automated Telegram brief delivery but does not pair that with clear warnings about recurring outbound messages, privacy implications, destination control, or credential handling. Users may enable ongoing automation without understanding that the agent could continue sending content externally on a schedule.
The quick-start workflow says the agent will set up a cronjob for Telegram delivery, but it does not explain persistence, how to audit or disable the job, what data will be transmitted, or how failures are handled. Persistent automation without safety disclosures can lead to accidental data leakage, unwanted spam, or hard-to-notice continued execution.
The auto-activation logic triggers on broad signals such as any Turkish-language input, then applies personality behavior or routes into domain-specific sub-skills. Over-broad activation can cause unintended tool use, unnecessary network access, or style/behavior changes during unrelated conversations, which weakens user consent and increases the chance of surprise actions.
The trigger list includes broad, common phrases such as "borsa", "hisse", "döviz", and "piyasa" that can match many ordinary Turkish conversations and cause the skill to activate outside the user's intended scope. In a finance-oriented skill, overbroad activation can lead to unintended web requests, irrelevant financial responses, and context hijacking from other more appropriate skills.
The file explicitly brands itself as a "Turkish Locale Skill Pack," and the implementation hard-codes Turkish formatting, timezone, labels, and TRY currency output. This creates a language/locale constraint without any visible opt-in or alternative locale selection, which matches the policy-violation criterion for forced language or locale.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
MAGENTA = "\033[95m"
# CoinGecko API
COINGECKO_MARKETS_API = "https://api.coingecko.com/api/v3/coins/markets"
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
The CLI help and inline documentation explicitly advertise cryptocurrency tracking, confirming that the mismatch is not accidental at runtime but documented into the skill itself. This increases the risk of operator deception and misuse because a human reviewer may assume the package is safe for BIST100 use while the executable interface encourages a different financial domain.
The file describes itself as a 'Turkish Locale Skill Pack', and its user-facing defaults and messaging are predominantly Turkish. This creates a language/locale constraint without offering the user a choice or opt-in, which matches the policy-violation criterion for forced language or locale.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# Sabitler / Constants
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
TELEGRAM_API_BASE = "https://api.telegram.org/bot{token}"
# Varsayılan caption (resim gönderiminde)
DEFAULT_CAPTION = "🌅 Günlük Brifing — Hermes Agent 🇹🇷"
The script transmits message content to an external third-party service, Telegram, including arbitrary text and optional fallback content. In an agent context, this becomes dangerous if sensitive internal data, summaries, or user content can be routed here without explicit authorization, because it creates a data egress path outside the local trust boundary.
}
try:
resp = requests.post(url, json=payload, timeout=15)
result = resp.json()
if result.get("ok"):
This code file includes natural-language descriptions and behavior that explicitly target Turkish output, such as Turkish-formatted dates and Turkish briefing text, but does not provide an opt-in or alternative locale selection. The policy requires flagging language or locale constraints unless they are clearly documented and justified as region-specific; here the file forces Turkish presentation for all runs of the script.
The trigger phrases are broad enough that normal conversation about a daily summary or morning news could activate this automation skill unexpectedly. Because the skill can schedule recurring jobs and send messages to external channels, accidental activation expands from a simple UX issue into unintended automated actions.
The manifest and documentation describe a Turkish daily brief skill that gathers news, markets, and weather for delivery via Telegram, Discord, or CLI. However, the self-contained cronjob prompt explicitly tells the future agent to run curl, introducing shell-style command execution rather than using the documented higher-level retrieval tools; this is broader than necessary for the stated purpose.
The CLI delivery mode writes files to a local directory without any explicit user-facing warning or consent step. Silent local file creation can surprise users, leak sensitive brief contents to shared systems, or create persistence artifacts the user did not intend.
No suspicious patterns detected.