T09 · Insecure Skill Coding Practices
- Location
scripts/tgcm.py:57- Finding
Path Traversal Through Unvalidated Channel Names
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Telegram channel automation skill is mostly coherent, but it handles powerful bot credentials and installation steps in ways users should review carefully before installing.
Install only if you are comfortable with an agent managing Telegram channel configuration, storing or discovering a bot token, creating cron jobs, and potentially posting approved pending content to a live channel. Prefer environment or secret-manager tokens, avoid config list/get for secrets, review cron prompts before enabling them, and do not run the SearXNG installer on a production host without pinning and isolating it.
scripts/tgcm.py:57Path Traversal Through Unvalidated Channel Names
scripts/tgcm.py:384Telegram Bot Token Stored and Printed in Plaintext
scripts/start-searxng.sh:5Mutable Remote Repository Is Downloaded, Installed, and Executed
scripts/start-searxng.sh:24Predictable Hardcoded SearXNG Secret
references/scout-prompt.md:29Untrusted Search Results Are Consumed Without Prompt-Injection Boundaries
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
file=sys.stderr,
)
return 1
meta["channelId"] = channel_id
meta["status"] = "connected"
save_channel_meta(channel_dir, meta)
sync_channels_index(workspace)
print(f"Channel '{name}' bound to {channel_id}")
return 0
def tg_api_call(token, method, params=None):
"""Call Telegram Bot API. Returns result dict or None on error."""
url = f"https://api.telegram.org/bot{token}/{method}"
if params:
url += "?" + urllib.parse.urlencode(params)
try:
with urllib.request.urlopen(url, timeout=10) as resp:
data = json.loads(resp.read().decode())
if data.get("ok"):
return data.get("result")
desc = data.get("description", "unknown error")
print(f"Telegram API {method}: {desc}", file=sys.stderr)
return None
except urllib.error.HTTPError as e:
desc = f"HTTP {e.code}"
try:
body = json.loads(e.read().decode())
desc = body.get("des
The declared description presents a broad, universal content pipeline engine for Telegram channels, including search, drafts, scheduling, deduplication, and config-driven channel abstraction. The supplied code chunk does only one narrow part of that scope: local deduplication checks and index maintenance using content-index.json. It does not perform SearXNG searches, draft handling, scheduling, or any config-driven channel-specific orchestration. While deduplication is mentioned in the description, the primary purpose of this code chunk is much narrower than the declared skill, so the description does not accurately represent what this code actually does.
The supplied code does not implement a Telegram content pipeline. It only provisions and starts a local SearXNG instance, including cloning the repository, installing dependencies, modifying configuration, and launching the service. While this may support the declared 'news search via SearXNG' aspect, it does not show the primary declared functionality: a universal config-driven engine for Telegram channels with drafts, scheduling, deduplication, and channel-specific behavior. Therefore the description materially overstates and misrepresents what this code chunk actually does.
The description presents a content pipeline engine centered on configurable channel-specific publishing workflows: news search through SearXNG, drafts, scheduled publishing, and deduplication. The supplied code instead implements a management CLI for channel setup and diagnostics. Its main behaviors are creating local channel folders and metadata files, binding Telegram channel IDs, checking bot token/channel access, querying Telegram Bot API for channel details and admins, resolving IDs, and handling a connect event by outputting a DM instruction payload. It also fetches existing posts from public Telegram channels by scraping t.me/s pages and stores lightweight dedup index entries. While there is some overlap with deduplication support and config handling, the primary purpose is materially different, and several declared core capabilities are absent: there is no scheduled publishing, no actual search against SearXNG, and no end-to-end draft/publishing pipeline. Additionally, the code performs undeclared Telegram introspection and scraping capabilities not reflected in the description.
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
def rebuild_index_instructions(channel_id):
"""Print instructions for rebuilding the index via Telegram search API."""
print("📋 Index rebuild via Telegram search API:")
print()
print("The agent should perform the following steps:")
The skill explicitly instructs the agent to use command execution, read/write local files, access environment variables, and perform network operations, yet it declares no tool scope or permission boundaries. This increases the risk of over-privileged execution because the runtime and reviewer cannot easily constrain what the skill may do.
The instruction to run commands autonomously and 'act on results, don't ask' reduces user confirmation before state-changing actions such as config writes or channel binding steps. In a skill that can execute commands, modify files, and use network resources, minimizing confirmation can lead to unintended changes and makes prompt-instruction abuse more dangerous.
## Execution
`python3` and `curl` are available in your environment (declared in `requires.bins`). Run all commands yourself using `exec`/`bash` tool. NEVER ask the user to run commands for you.
## Startup
The startup flow tells the agent to ask for and save credentials or env-like settings, while a later section says not to ask for bot tokens or env vars. Contradictory instructions around secret acquisition and handling can cause unsafe agent behavior, including prompting for sensitive data when it should rely on existing resolution paths or provide safer guidance.
The skill instructs storing a Telegram bot token locally in tgcm/.config.json without clearly warning the user that this is a persistent credential write. A bot token grants control over the bot and possibly channel-management operations, so accidental storage in a shared workspace, insecure repo, or readable filesystem can lead to account compromise.
The documentation describes setting up unattended publishing jobs that post directly to a live Telegram channel, but it does not warn users that these commands automate public-facing publication. In a content pipeline skill, this omission increases the chance of accidental live posts, misuse of drafts, or publication of unreviewed/generated content, especially when cron jobs are configured from reusable templates.
The prompt is framed as a generic 'Cron: Publisher' workflow and directly instructs the agent to publish to a live Telegram channel, but it does not define strong activation boundaries, confirmation requirements, or environmental safeguards. In an agent system where prompts may be invoked broadly or misrouted, this ambiguity can cause unintended publication actions against production channels without explicit human approval.
The instruction to remove the published entry from content-queue.md is a destructive state change, yet the prompt provides no warning, backup, audit trail, or transactional safeguard around that deletion. If publication fails partially, targets the wrong post, or the agent misidentifies state, queued content can be silently lost or corrupted, making recovery and forensic review difficult.
This markdown file describes the skill's task and behavior but does not define any specific invocation phrases, scope boundaries, or negative examples for activation. Phrases like 'Find fresh news and write drafts' are operationally broad, which can lead to unintended invocation if used as the basis for routing or activation.
The skill instructs the agent to modify repository content by appending drafts to content-queue.md, but it provides no user-facing warning or approval checkpoint before making persistent changes. In agentic environments, silent file mutation can lead to unauthorized repository edits, workflow poisoning, or accidental propagation of low-quality or adversarial content into downstream publishing systems.
The prompt directs the agent to perform external network requests with curl to a configurable SearXNG endpoint, without any warning, allowlist, or consent boundary. This can expose the environment to SSRF-like behavior if SEARXNG_URL is attacker-controlled, leak metadata through outbound requests, or retrieve untrusted content that influences subsequent repository writes.
The skill is described as a config-driven Telegram channel content pipeline, but this CLI also searches the current directory and the user's home directory for an external openclaw.json file to extract credentials. Pulling secrets from unrelated global config locations is not an obvious requirement for managing Telegram channels and expands the skill's access to ambient credentials.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def tg_api_call(token, method, params=None):
"""Call Telegram Bot API. Returns result dict or None on error."""
url = f"https://api.telegram.org/bot{token}/{method}"
if params:
url += "?" + urllib.parse.urlencode(params)
try:
The config command stores sensitive bot tokens in plaintext in tgcm/.config.json and the list action prints all saved values, which can expose credentials to local users, shell history capture, logs, screenshots, or CI output. Credential disclosure would let anyone with the token control the Telegram bot and act against connected channels.
The Quick Reference maps user requests using Russian phrases such as «узнай/определи channel-id» and «подключи канал», which suggests a language-specific interaction pattern. The file does not explicitly offer multilingual support or justify that the skill is intended only for Russian-speaking users.
The curl example hard-codes 'language=en' for search, which imposes a specific language/locale behavior. The file does not indicate that this is optional, user-configurable, or justified as a region-specific requirement.
The rule 'Post language: config.language' indicates the skill will enforce a specific output language, but this file does not mention user choice, opt-in, or a justified regional constraint. That can violate language/locale policy when users are not given a choice.
The manifest focuses on news search, drafts, scheduled publishing, and deduplication for Telegram channels. The --admins and detailed --permissions capabilities inspect channel administrators and privilege metadata, which are management/introspection features not clearly justified by the stated content pipeline scope.