Back to skill

Security audit

Telegram Multilingual Voice Reply

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it can leave private Telegram audio, generated speech, and transcript files on disk without a clear retention policy.

Review before installing. Use this only on a trusted machine and account, and consider patching cleanup for temporary files or manually clearing the temp directories after use. The reviewed artifacts did not show exfiltration, destructive behavior, credential theft, or persistence beyond retained temp artifacts, but the retained audio/transcript data is a real privacy issue.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mlx_asr.py:76
Finding

Temporary audio and transcript artifacts are retained after processing

Content
View full analysis

Vulnerability Details

File Location: scripts/mlx_asr.py:76-82, scripts/mlx_asr.py:99, and scripts/mlx_tts_voice.py:52-53
Vulnerability Type: Insecure temporary-file lifecycle and sensitive-data retention
Risk Level: Medium

Vulnerable Code

scripts/mlx_asr.py:76-82:

python
def _ffmpeg_to_wav(src: Path) -> Path:
    """Convert audio to 16k mono wav using ffmpeg (best-effort)."""
    import subprocess
    import tempfile

    out = Path(tempfile.mkstemp(prefix="mlx_asr_", suffix=".wav")[1])
    cmd = ["ffmpeg", "-y", "-i", str(src), "-ac", "1", "-ar", "16000", str(out)]
    p = subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

scripts/mlx_asr.py:99:

python
    out_prefix = Path(tempfile.mkdtemp(prefix="mlx_asr_out_")) / "out"

scripts/mlx_tts_voice.py:52-53:

python
    tmpdir = Path(tempfile.mkdtemp(prefix="mlx_tts_"))
    mp3_path = tmpdir / "reply.mp3"

Technical Analysis

The ASR script creates a temporary WAV containing converted user speech and a temporary output directory in which the external mlx_audio command can store transcripts or JSON results. The TTS script similarly creates a temporary directory containing an MP3 representation of the generated reply.

None of these temporary files or directories are deleted on successful completion or on an error path. Consequently, private source speech, generated speech, and transcript data may remain on local storage indefinitely.

In addition, tempfile.mkstemp() returns an open file descriptor and a path. The code retains only the path and does not close the returned descriptor. Repeated processing can therefore leak file descriptors until the Python process terminates. The temporary names themselves are securely generated, so this is not a predictable-name or symlink vulnerability; the primary risks are sensitive-data retention and resource leakage.

Attack Path

...[truncated 1647 chars]

Remediation
View remediation

Remediation Suggestions

  • Use tempfile.TemporaryDirectory() as a context manager for all intermediate directories so they are recursively removed after processing.
  • Use tempfile.NamedTemporaryFile() as a context manager for converted audio where platform behavior permits.
  • If mkstemp() remains necessary, preserve and immediately close its descriptor with os.close(fd).
  • Place cleanup in a finally block so artifacts are removed after both successful processing and exceptions.
  • Delete partial output files when ffmpeg or mlx_audio fails.
  • Avoid writing transcripts to disk when standard output or an in-memory API is available.
  • Apply restrictive permissions to temporary directories and files as defense in depth.
  • Consider an explicit retention policy if artifacts must be preserved for diagnostics, with user consent, short expiration periods, and secure deletion where supported.

Example hardening pattern:

python
import os
import shutil
import tempfile
from pathlib import Path

tmpdir = Path(tempfile.mkdtemp(prefix="mlx_asr_out_"))
try:
    out_prefix = tmpdir / "out"
    # Run processing and consume the result.
finally:
    shutil.rmtree(tmpdir, ignore_errors=True)

fd, temporary_name = tempfile.mkstemp(prefix="mlx_asr_", suffix=".wav")
os.close(fd)
temporary_path = Path(temporary_name)
try:
    # Convert and process the audio.
    pass
finally:
    temporary_path.unlink(missing_ok=True)
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose describes an end-user Telegram automation workflow: detect incoming message type, transcribe voice locally, generate a meaningful reply in the same language, and return one Telegram voice message plus caption whose text matches the audio exactly. The supplied code does not implement any Telegram integration, message handling, reply generation, language-following conversation logic, or voice-note synthesis/sending. Instead, it is a utility script whose primary purpose is local ASR and optional forced alignment via mlx_audio, with multiple output formats. That is a materially different scope and purpose from the declared workflow, so this is a clear mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description is for an end-to-end smart Telegram responder: detect whether the user sent text or audio, transcribe audio locally, generate a reply in the same language, and send back a single Telegram voice note with matching caption text. The supplied code does not implement that workflow. It only converts provided text into speech using mlx_audio and ffmpeg, producing an OGG/OPUS file suitable for Telegram voice notes. There is no Telegram API interaction, no input classification, no ASR/transcription, no reply generation, and no enforcement that a caption matches the spoken output. While this script could be a supporting utility within the larger described system, the code chunk itself materially under-implements the declared purpose, so the description does not accurately represent what this code actually does.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs the agent to invoke shell commands and read local files/scripts, but it declares no tool scope or allowed-tools boundary. In an agent environment, missing tool restrictions increases the chance that the skill can access more filesystem or command execution capability than intended, especially if later modified or combined with untrusted inputs.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/mlx_asr.py (reported line 81)May include surrounding context.

python
out = Path(tempfile.mkstemp(prefix="mlx_asr_", suffix=".wav")[1])
    cmd = ["ffmpeg", "-y", "-i", str(src), "-ac", "1", "-ar", "16000", str(out)]
    p = subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    if p.returncode != 0 or not out.exists():
        raise RuntimeError("ffmpeg conversion failed")
    return out

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest describes a Telegram workflow that transcribes incoming voice/audio locally and replies in the same language, but this script also supports a separate forced-alignment mode via --text and --align-model. Forced alignment is a distinct capability for timestamping a supplied transcript against audio, and it is not mentioned as part of the skill’s stated purpose.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/mlx_asr.py (reported line 116)May include surrounding context.

python
if args.language:
        cmd += ["--language", args.language]

    p = subprocess.run(cmd, capture_output=True, text=True)
    if p.returncode != 0:
        print("ERROR: mlx_audio.tts.generate failed", file=sys.stderr)
        print(p.stderr or p.stdout, file=sys.stderr)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/mlx_tts_voice.py (reported line 78)May include surrounding context.

python
if args.language:
        cmd += ["--language", args.language]

    p = subprocess.run(cmd, capture_output=True, text=True)
    if p.returncode != 0:
        print("ERROR: mlx_audio.tts.generate failed", file=sys.stderr)
        print(p.stderr or p.stdout, file=sys.stderr)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/mlx_tts_voice.py (reported line 89)May include surrounding context.

python
return 4

    # Convert to ogg/opus for Telegram voice notes
    ff = subprocess.run(
        [
            "ffmpeg",
            "-y",

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The top-level documentation presents the file primarily as a stable entrypoint for STT, while the implementation includes a separate operational mode for forced alignment. Because the inline documentation emphasizes transcription behavior but the code performs an additional alignment task, the documentation does not accurately reflect the script’s actual intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The script invokes external binaries via subprocess for ffmpeg conversion and mlx_audio CLI execution, which are safety-relevant operations for code files. Although the module docstring mentions ffmpeg best-effort conversion, there is no runtime confirmation, logging, or user-facing notice when these subprocesses are actually executed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
63% confidence
Finding

The natural-language help text gives only specific language examples, which may implicitly steer users toward a narrow language/locale expectation. This is a weak policy concern because the parameter itself is configurable, but the wording does not explicitly emphasize unrestricted user choice.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.