Back to skill

Security audit

Telegram Voice Bot

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it handles private voice messages in ways that are under-disclosed and has a dependency mismatch that could create supply-chain risk.

Review before installing. Use a dedicated Telegram bot token and low-privilege runtime account, replace 'whisper' with the intended reviewed package, pin dependencies or use a lock file, disable or remove full transcript logging, and disclose to bot users that their audio/text may be processed by Telegram and Microsoft Edge TTS.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T08 · Insecure Dependencies

Error
Location
requirements.txt:1
Finding
Incorrect and Unpinned Whisper Dependency Creates a Supply-Chain Risk## Vulnerability Details **File Location**: `requirements.txt:1-3` **Vulnerability Type**: Dependency-name mismatch and unpinned third-party packages **Risk Level**: High ### Evidence ```text requests whisper edge-tts ``` ### Technical Analysis The project documentation declares `openai-whisper` as the required speech-recognition package, but `requirements.txt` installs the differently named `whisper` package. Although OpenAI Whisper is imported in Python using `import whisper`, its distribution name is `openai-whisper`. This mismatch can cause installation of an unintended package from the configured package index. In addition, none of the three dependencies is pinned to a reviewed version or protected by package hashes. A future compromised or malicious release could therefore be selected automatically during installation. Python package installation and subsequent imports can execute package-controlled code. Such code would run with the privileges of the user or service account installing or launching the bot. ### Attack Path 1. A user follows the documented installation command: `pip install -r requirements.txt`. 2. The package index resolves `whisper` rather than the documented `openai-whisper` distribution. 3. Because no versions or hashes are specified, the installer accepts whichever matching releases the package index currently selects. 4. An unintended or compromised package can execute code during installation or when imported by `bot.py`. 5. That code runs under the installing or bot service account and can access resources available to that account, including the bot environment and `TELEGRAM_BOT_TOKEN`. Exploitation requires an unintended or compromised dependency to be served by the configured package index; the audited repository itself does not contain such a payload. ### Impact Assessment Successful supply-chain exploitation could provide arbitrary code execution with the privileges of the ...[truncated 567 chars]
Remediation
## Remediation Suggestions 1. Replace `whisper` with the correct, reviewed `openai-whisper` distribution. 2. Pin every direct dependency to an explicitly reviewed version, for example: ```text requests==<reviewed-version> openai-whisper==<reviewed-version> edge-tts==<reviewed-version> ``` 3. Generate a lock file containing pinned transitive dependencies. 4. Require package hashes during deployment, such as through a hash-locked requirements file and `pip install --require-hashes`. 5. Install only from an approved package index and disable unintended fallback indexes. 6. Run dependency vulnerability and provenance checks in CI before releasing or deploying the Skill. 7. Install and execute the bot under a dedicated, unprivileged service account with access only to required files and environment variables.

T09 · Insecure Skill Coding Practices

Warning
Location
bot.py:146
Finding
Private Voice Transcripts Are Written to Process Logs## Vulnerability Details **File Location**: `bot.py:146-151` **Vulnerability Type**: Plaintext sensitive-data exposure through logging **Risk Level**: Medium ### Evidence ```python text = transcribe_audio(audio_data, model) if text: print(f"Transcribed: {text}") # Reply with voice reply = f"你说了:{text}" send_voice(chat_id, reply) ``` ### Technical Analysis The bot writes the complete Whisper transcript to standard output. Logging message content is not necessary to perform transcription or return the declared voice response. Standard output is commonly captured by container runtimes, service managers, CI systems, terminal recording, or centralized logging services. Consequently, private speech content can be copied into storage with different access controls and retention periods from the original Telegram message. No authorization check, redaction, retention control, or opt-in debugging guard protects the transcript log statement. ### Attack Path 1. A Telegram user sends a voice message to the bot. 2. The bot downloads the audio and transcribes it locally with Whisper. 3. The complete transcript is passed to `print`. 4. The execution environment captures standard output in a terminal, service journal, container log, or log aggregation platform. 5. A person or system with access to those logs can read the user's transcribed speech, potentially after the original Telegram message has been deleted. This path requires access to the bot's process output or downstream logs; the finding does not by itself grant such access. ### Impact Assessment The issue can disclose the full textual content of processed voice messages to operators, administrators, support personnel, or log-platform accounts that were not intended to receive message content. The affected scope includes every successfully transcribed voice message while the statement is enabled. Potential consequences include privacy loss, ...[truncated 206 chars]
Remediation
## Remediation Suggestions 1. Remove the full-content logging statement: ```python print(f"Transcribed: {text}") ``` 2. Log only non-sensitive operational metadata, such as whether transcription succeeded and its processing duration. 3. If transcript logging is required for troubleshooting, place it behind an explicit debug setting that is disabled by default. 4. Redact sensitive values and truncate content before any diagnostic logging. 5. Restrict access to process and centralized logs, encrypt retained logs, and configure short retention periods. 6. Document any intentional message-content logging and obtain appropriate user consent before enabling it.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (22)

YARA rule 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Content
Chinese language support

Usage:
    python bot.py
    
Environment variables:
    TELEGRAM_BOT_TOKEN - Your Telegram Bot Token (get from @BotFather)
    VOICE_REPLY - Set to "true" to enable voice reply (default: true)
"""
import os
import time
import asyncio
import requests
import whisper
import tempfile
import uuid
import edge_tts
from pathlib import Path

# Configuration
TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
BASE_URL = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}"
VOICE_REPLY = os.environ.get("VOICE_REPLY", "true").lower() == "true"

# Whisper model options: tiny, base, small, medium, large
MODEL_NAME = "base"

# Default voice for TTS
DEFAULT_VOICE = "zh-CN-XiaoxiaoNeural"

def load_model():
    """Load Whisper model"""
    print(f"Loading Whisper model: {MODEL_NAME}...")
    model = whisper.load_model(MODEL_NAME)
    print("Model loaded!")
    return model

async def synthesize_speech(text, output_file):
    """Generate speech using edge-tts"""
    t
Confidence
85% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Tainted flow: 'BASE_URL' from os.environ.get (line 29, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
def get_updates(offset=0):
    """Get updates from Telegram"""
    try:
        resp = requests.get(
            f"{BASE_URL}/getUpdates",
            params={"offset": offset, "timeout": 30},
            timeout=35
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'BASE_URL' from os.environ.get (line 29, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
def download_file(file_id):
    """Download voice file from Telegram"""
    try:
        resp = requests.get(f"{BASE_URL}/getFile", params={"file_id": file_id}, timeout=10)
        data = resp.json()
        
        if not data.get("ok"):
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'file_url' from os.environ.get (line 78, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
file_path = data["result"]["file_path"]
        file_url = f"https://api.telegram.org/file/bot{TELEGRAM_BOT_TOKEN}/{file_path}"
        resp = requests.get(file_url, timeout=30)
        return resp.content
        
    except Exception as e:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'BASE_URL' from os.environ.get (line 29, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
def send_message(chat_id, text):
    """Send text message"""
    try:
        requests.post(
            f"{BASE_URL}/sendMessage",
            json={"chat_id": chat_id, "text": text},
            timeout=10
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'BASE_URL' from os.environ.get (line 29, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
with open(temp_path, "rb") as f:
            files = {"voice": ("reply.ogg", f, "audio/ogg")}
            data = {"chat_id": chat_id}
            requests.post(
                f"{BASE_URL}/sendVoice",
                data=data,
                files=files,
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'BASE_URL' from os.environ.get (line 29, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
# Test API
    try:
        resp = requests.get(f"{BASE_URL}/getMe", timeout=10)
        if not resp.json().get("ok"):
            print("Error: Invalid bot token!")
            return
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The skill description presents Chinese voice recognition and voice replies as the default behavior without indicating any user choice, opt-in, or notice before processing spoken content. In a messaging bot context, automatic voice handling can expose user content unexpectedly and increases privacy risk, especially when combined with external speech/TTS processing.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The README states that voice messages are processed using external speech recognition and TTS components, but it does not warn users or operators that audio content may leave the local trust boundary or be handled by third-party software/services. This creates a real privacy and compliance risk because sensitive voice content could be transmitted, logged, or retained without informed consent or operator awareness.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The skill defaults to Chinese support and Chinese voice synthesis without indicating user choice, which can lead to unexpected processing, miscommunication, or exclusion of users who did not intend to use that language. In a voice bot context, lack of explicit language selection can also increase privacy and usability risk if messages are interpreted or spoken in an unintended language.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill advertises voice recognition and TTS using third-party services but does not warn users that voice content may be transmitted off-platform for processing. This creates a privacy and consent risk because users may disclose sensitive audio without understanding that external providers may receive, process, or retain that data.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The file advertises 'Full Chinese language support' and the implementation hard-codes both Chinese transcription and a Chinese TTS voice. This imposes a specific language/locale on all users without offering opt-in, selection, or documenting a region-specific requirement.

External Transmission

Medium
Category
Data Exfiltration
Content
# Configuration
TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
BASE_URL = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}"
VOICE_REPLY = os.environ.get("VOICE_REPLY", "true").lower() == "true"

# Whisper model options: tiny, base, small, medium, large
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Configuration
TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
BASE_URL = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}"
VOICE_REPLY = os.environ.get("VOICE_REPLY", "true").lower() == "true"

# Whisper model options: tiny, base, small, medium, large
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The default TTS voice is fixed to 'zh-CN-XiaoxiaoNeural', which enforces a Chinese locale for replies. Because no alternative or user-controlled locale is offered, this is a natural-language policy issue rather than a technical defect.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
The transcription call sets `language="zh"`, forcing recognition in Chinese for every voice message. This removes user language choice and can exclude users in other locales without a documented business or compliance justification.

External Transmission

Medium
Category
Data Exfiltration
Content
def send_message(chat_id, text):
    """Send text message"""
    try:
        requests.post(
            f"{BASE_URL}/sendMessage",
            json={"chat_id": chat_id, "text": text},
            timeout=10
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Tainted flow: 'data' from requests.get (line 72, network input) → requests.post (network output)

Medium
Category
Data Flow
Content
with open(temp_path, "rb") as f:
            files = {"voice": ("reply.ogg", f, "audio/ogg")}
            data = {"chat_id": chat_id}
            requests.post(
                f"{BASE_URL}/sendVoice",
                data=data,
                files=files,
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests
whisper
edge-tts
Confidence
97% confidence
Finding
The dependency 'requests' is declared without a version pin, which makes builds non-reproducible and can cause the environment to resolve to a vulnerable or incompatible release over time. In a security-sensitive agent skill, this increases supply-chain risk because the actual installed version cannot be verified against known advisories.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding
The manifest references 'requests' without a pinned version even though multiple advisories exist for some releases of that package. Because the exact version is unknown, it is impossible to determine whether deployments are exposed, and the ambiguity itself is a supply-chain risk in environments that may fetch the latest matching release.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests
whisper
edge-tts
Confidence
95% confidence
Finding
The dependency 'whisper' is unpinned, so installations may pull different releases at different times. This weakens reproducibility and makes it harder to verify whether the resolved package version contains security flaws or breaking changes.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests
whisper
edge-tts
Confidence
95% confidence
Finding
The dependency 'edge-tts' is also unpinned, creating the same supply-chain and reproducibility risk as the other packages. An attacker controlling or compromising an upstream release channel could have a better chance of affecting future installs when exact versions are not fixed.

Static analysis

No suspicious patterns detected.