T09 · Insecure Skill Coding Practices
- Location
reader.py:702- Finding
Predictable Shared Temporary Files Are Used for Telegram Login Secrets
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a legitimate Telegram channel reader, but it needs Review because its login flow and stored session can expose sensitive Telegram account data if used carelessly.
Install only if you are comfortable granting this skill access to a Telegram account session that can read private channels available to that account. Prefer self-authentication or stdin over /tmp code/password files, avoid using the Telethon auth output in logged environments, keep session and backup files private, and install in a dedicated virtual environment with reviewed dependency versions where possible.
reader.py:702Predictable Shared Temporary Files Are Used for Telegram Login Secrets
reader_telethon.py:625Telethon Authentication Logs the Account Phone Number
setup.py:15Security-Sensitive Dependencies Are Installed Without Exact Version or Hash Pinning
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
led, uninstall it first — they share a namespace. pip uninstall pyrogram -y 2>/dev/null pip install pyrofork tgcrypto telethon pip install -e .
> **Linux users:** if you get `externally-managed-environment` error, use a virtual environment:
> ```bash
> python3 -m venv ~/.venv/tg-reader
> ~/.venv/tg-reader/bin/pip install pyrofork tgcrypto telethon
> ~/.venv/tg-reader/bin/pip install -e .
> echo 'export PATH="$HOME/.venv/tg-reader/bin:$PATH"' >> ~/.bashrc
> source ~/.bashrc
> ```
## Manual Install
```bash
cd ~/.openclaw/workspace/skills
git clone https://github.com/bzSega/sergei-mikhailov-tg-channel-reader
cd sergei-mikhailov-tg-channel-reader
pip install pyrofork tgcrypto telethon
pip install -e .
You need a personal Telegram API key. This is free and takes 2 minutes.
+79991234567) and click Send CodeYARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
workspace/skills/sergei-mikhailov-tg-channel-reader bash setup-tg-reader.sh
The setup script: installs Python packages (`pip install .`), checks credentials and session, runs `tg-reader-check`, and prints the exec approval commands for you to run manually.
On Linux with managed Python (Ubuntu/Debian), use a venv **before** running the setup script:
```bash
python3 -m venv ~/.venv/tg-reader
echo 'export PATH="$HOME/.venv/tg-reader/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc
cd ~/.openclaw/workspace/skills/sergei-mikhailov-tg-channel-reader
# pyrofork replaces pyrogram; uninstall pyrogram first if it was already installed
pip uninstall pyrogram -y 2>/dev/null
pip install pyrofork tgcrypto telethon && pip install .
openclaw approvals allowlist add --gateway "$(which tg-reader)"
openclaw approvals allowlist add --gateway "$(which tg-reader-check)"
tg
The changelog advertises a setup script that automatically adds commands to an exec approval allowlist, which weakens an explicit security control by pre-approving future command execution. In an agent-driven environment, silently normalizing or encouraging automatic allowlisting can increase the blast radius of prompt injection or command abuse, especially if users do not clearly understand what is being trusted.
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.
## [0.8.7] - 2026-03-01
**Write output to a file instead of flooding the agent's context.** New `--output` flag saves fetch results (especially large comment payloads) to a file. The agent gets a short confirmation on stdout instead of the full JSON — saving tokens. Works great with cron: schedule periodic updates to a file, then analyze on demand without re-fetching.
### Added
- `--output` flag for `fetch` command — writes results to a file instead of stdout
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
### Security
- `test_session.py`: replaced partial `api_hash[:10]` print with masked output (`***`) to prevent secret leakage in logs or shared terminals
- `SKILL.md`: added `chmod 600` step after auth to restrict session file permissions
---
The README instructs users to install via npx clawhub@latest, which pulls and executes the latest published package without pinning a specific version. If the upstream package or dependency chain is compromised, users may run unexpected code during installation.
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.
- **App title**: any name (e.g. `MyReader`)
- **Short name**: any short word (e.g. `myreader`)
- Other fields can be left as default
6. Click **"Create application"**
7. You'll see your credentials:
- **App api_id** — a number like `12345678`
- **App api_hash** — a 32-character string like `a1b2c3d4e5f6789012345678abcdef12`
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
"api_hash": "your_api_hash_here" } EOF chmod 600 ~/.tg-reader.json
Works everywhere — agents, servers, interactive shells. File is outside the project and never committed.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
"api_hash": "your_api_hash_here" } EOF chmod 600 ~/.tg-reader.json
Works everywhere — agents, servers, interactive shells. File is outside the project and never committed.
The suggested trigger phrases such as "check", "read", or "monitor" a Telegram channel are broad and overlap with normal user language. In agentic systems, this can cause unintended activation of the skill in contexts where the user did not explicitly consent to using Telegram account-backed tooling.
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.
# Human-readable output
tg-reader fetch @channel_name --since 24h --format text
# Write output to file instead of stdout (saves tokens)
tg-reader fetch @channel_name --since 24h --output
tg-reader fetch @channel_name --since 24h --comments --output comments.json
The skill explicitly directs users to store long-lived Telegram API credentials in ~/.tg-reader.json. Although presented as setup guidance, this creates persistent local secret storage tied to a tool that also manages full-account session files, increasing the impact of host compromise or accidental file disclosure.
### Step 1 — Get API Credentials
Go to https://my.telegram.org → **API Development Tools** → create an app → copy `api_id` and `api_hash`.
### Step 2 — Save Credentials
The skill instructs users to install via npx clawhub@latest, which fetches and executes the latest remote package without pinning a version or integrity hash. If the upstream package is compromised or a breaking release is published, users may execute unreviewed code during installation.
The skill advertises itself as a channel reader but includes substantially broader capabilities: full Telegram account authorization, session backup/restore, and lifecycle management. This scope expansion increases the trust required from the user and creates a larger attack surface around account access and credential handling than a simple reader would need.
The code writes auth-progress data to a file path taken directly from the TG_AUTH_PROGRESS environment variable without validation. In environments where untrusted callers can influence environment variables, this enables arbitrary file append/write as the running user, which can overwrite logs, poison state files, or target sensitive paths via symlinks.
progress = os.environ.get("TG_AUTH_PROGRESS")
if progress:
try:
with open(progress, "a") as f:
f.write(line + "\n")
except OSError:
pass
The code persists phone numbers and manages long-lived authentication state, which is sensitive account metadata beyond the minimum required to merely fetch channel content. In an agent setting with unclear purpose boundaries, retaining such data increases privacy risk and the consequences of filesystem compromise or misuse by other local components.
This section actively initiates Telegram login by sending codes, accepting login codes and 2FA passwords, and installing new sessions. That is a materially stronger capability than reading public/private channels and, if invoked by an untrusted or over-permissioned agent workflow, could enroll or switch Telegram accounts without sufficiently clear separation of duties.
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.
def _write_output(result, output_path, fmt, since_label):
"""Write output to a file and print a short confirmation to stdout."""
output_path = os.path.abspath(output_path)
with open(output_path, "w", encoding="utf-8") as f:
if fmt == "json":
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.
"error": f"Session file not found: {session_file}",
"expected_path": str(session_file),
"fix": [
"Run 'tg-reader-telethon auth' to create a new session",
"Or set TG_SESSION=/path/to/existing-session (without .session suffix)",
"Or add {\"session\": \"/path/to/session\"} to ~/.tg-reader.json",
"Or pass --session-file /path/to/session (without .session suffix)",
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.
"error": f"Session file not found: {session_file}",
"expected_path": str(session_file),
"fix": [
"Run 'tg-reader-telethon auth' to create a new session",
"Or set TG_SESSION=/path/to/existing-session (without .session suffix)",
"Or add {\"session\": \"/path/to/session\"} to ~/.tg-reader.json",
"Or pass --session-file /path/to/session (without .session suffix)",
The interactive auth flow prints sensitive account identifiers, including the user's phone number and account identity, directly to stdout and in JSON output. In agent, CI, terminal-logging, or orchestrated environments, stdout is often captured, persisted, or forwarded, which can expose personal data beyond the immediate user.
Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.
for name in ("pyrogram", "telethon", "tgcrypto"):
try:
mod = __import__(name)
version = getattr(mod, "__version__", "unknown")
result[name] = {"installed": True, "version": version}
except ImportError:
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.
"""Online check: does the resolved session hold an authorized user?
Runs only when the session file exists — connecting with a missing file
would CREATE a fresh unauthorized session file as a side effect. Takes the
session lock (short timeout) so it never races a running fetch.
Returns:
The text instructs the agent to reassure the user that the session never leaves the machine, which is persuasive language that can bias the user's risk assessment rather than neutrally presenting facts. In security-sensitive auth flows, agent instructions that push reassurance can reduce informed consent and make users less likely to scrutinize storage, access, or backup behavior.
The cron setup instructions say to include the exact 'tg-reader' command in the task description, but they do not define how narrowly the reminder should be phrased or what descriptions should not trigger the skill. In a manifest-like instruction context, this can create ambiguity about when the agent should invoke the skill from scheduled reminders.
No suspicious patterns detected.