Back to skill

Security audit

微信频道语音+视频实现气泡自动播报模式

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent video-generation purpose, but its output handling can overwrite files outside its intended folder and it sends user text/prompts to external services.

Review before installing. Do not use sensitive text or private prompts unless you are comfortable sending them to the TTS and image-generation providers. Run the script with a simple .mp4 filename only, avoid privileged accounts, and prefer a hardened version that confines output to its own folder and uses per-run temporary files.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/make_video.py:35
Finding

Arbitrary File Overwrite Through Output Path Traversal

Content
View full analysis

Vulnerability Details

File Location: scripts/make_video.py, lines 35-57
Vulnerability Type: Unrestricted output path and arbitrary file overwrite
Risk Level: Medium

python
def make_video(audio_path, image_path, output_video):
    """合成视频"""
    cmd = [
        FFMPEG,
        "-loop", "1", "-i", image_path,
        "-i", audio_path,
        "-c:v", "libx264", "-tune", "stillimage", "-pix_fmt", "yuv420p",
        "-c:a", "aac", "-b:a", "128k",
        "-shortest", "-y", output_video
    ]
    subprocess.run(cmd, check=True)
    return output_video

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--text", required=True, help="要朗读的文本")
    parser.add_argument("--bg_prompt", default="Beautiful elegant Chinese lady, soft lighting, cinematic, 4k", help="背景图描述")
    parser.add_argument("--output", default="result.mp4", help="输出文件名")
    args = parser.parse_args()

    audio_file = os.path.join(OUTPUT_DIR, "temp_audio.mp3")
    image_file = os.path.join(OUTPUT_DIR, "temp_bg.png")
    final_video = os.path.join(OUTPUT_DIR, args.output)

Technical Analysis

The --output argument is accepted without validating that it is a simple filename. It is joined directly to OUTPUT_DIR using os.path.join.

An absolute path supplied as args.output can cause os.path.join to discard the intended base directory. Relative path components such as ../ can also resolve outside OUTPUT_DIR. The resulting attacker-controlled path is passed to FFmpeg together with -y, which instructs FFmpeg to overwrite an existing destination without confirmation.

Although the program uses an argument list rather than a shell command and is therefore not directly vulnerable to shell command injection, it does not enforce the intended filesystem boundary.

Attack Path

  1. An attacker or untrusted caller gains control over the value passed to --output.
  2. The attacker s ...[truncated 966 chars]
Remediation
View remediation

Remediation Suggestions

  • Treat --output strictly as a filename rather than a path.
  • Reject absolute paths, .. components, directory separators, and unexpected file extensions.
  • Resolve the candidate destination with os.path.realpath and verify that it remains beneath the canonical output directory.
  • Use os.path.commonpath for containment checks rather than string-prefix comparisons.
  • Allow only an expected extension such as .mp4.
  • Avoid unconditional FFmpeg -y; require an explicit overwrite option or fail if the destination already exists.
  • Run the media-generation process with a minimally privileged operating-system account.

Example hardening logic:

python
output_root = os.path.realpath(OUTPUT_DIR)
output_name = os.path.basename(args.output)

if output_name != args.output or not output_name.lower().endswith(".mp4"):
    parser.error("--output must be a simple .mp4 filename")

final_video = os.path.realpath(os.path.join(output_root, output_name))
if os.path.commonpath([output_root, final_video]) != output_root:
    parser.error("Output path escapes the designated output directory")

T09 · Insecure Skill Coding Practices

Note
Location
scripts/make_video.py:55
Finding

Predictable Shared Temporary Files Permit Cross-Job Interference

Content
View full analysis

Vulnerability Details

File Location: scripts/make_video.py, lines 55-56
Vulnerability Type: Unsafe and predictable temporary file handling
Risk Level: Low

python
    audio_file = os.path.join(OUTPUT_DIR, "temp_audio.mp3")
    image_file = os.path.join(OUTPUT_DIR, "temp_bg.png")

Technical Analysis

Every invocation uses the same fixed paths, temp_audio.mp3 and temp_bg.png. The files are placed in the shared output directory instead of a private, unpredictable, per-run temporary directory.

Concurrent executions can overwrite these files between generation and video assembly. Consequently, one invocation may incorporate audio or imagery belonging to another invocation. Where another local actor can write to OUTPUT_DIR, that actor may also pre-create files or filesystem links at these predictable paths. The precise link behavior and resulting overwrite scope depend on the operating system, filesystem, and behavior of the external TTS and FFmpeg tools.

The files are also not removed after processing, leaving generated narration and images on disk beyond the lifetime of the operation.

Attack Path

  1. A victim starts a video-generation job, which uses the fixed temporary filenames.
  2. A second concurrent job or a local actor with write access to OUTPUT_DIR writes to one of the same paths before the victim completes video assembly.
  3. The victim's FFmpeg process reads the replaced temporary asset.
  4. The resulting video contains another job's or the attacker's media, or the victim's operation fails because the file is incomplete or malformed.
  5. On platforms that permit exploitable filesystem links in this context, a pre-created link may additionally redirect a write performed by an external tool.

Impact Assessment

The primary impacts are cross-job data leakage, incorrect output, denial of service, and loss of integrity in generated videos. Narration or background imagery from one u ...[truncated 329 chars]

Remediation
View remediation

Remediation Suggestions

  • Create a private temporary directory for each invocation with tempfile.TemporaryDirectory.
  • Store all intermediate audio and image files inside that directory using non-predictable names.
  • Ensure the temporary directory is accessible only to the process owner.
  • Remove intermediate assets in a finally block; TemporaryDirectory can handle cleanup automatically.
  • Keep only the completed MP4 in the designated output directory.
  • If multiple processes can produce the same final filename, use exclusive file creation, unique output names, or an application-level lock.

Example hardening pattern:

python
import tempfile

with tempfile.TemporaryDirectory(prefix="voice-document-") as temp_dir:
    audio_file = os.path.join(temp_dir, "audio.mp3")
    image_file = os.path.join(temp_dir, "background.png")

    generate_tts(args.text, audio_file)
    generate_cover(args.bg_prompt, image_file)
    make_video(audio_file, image_file, final_video)
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill advertises and invokes capabilities that imply shell execution and network access, but it does not declare any tool scope or permission boundaries. This weakens reviewability and runtime control, making it easier for the skill to invoke external services or local commands without explicit governance.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description says it sends text to TTS and image-generation services and produces an MP4, but it does not warn users that their supplied text and prompts may leave the local environment or that files will be created on disk. This can cause unintentional disclosure of sensitive content and unexpected file generation, especially if users provide private documents or proprietary prompts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

User-provided text is sent to an external TTS service via the edge_tts module, but the script gives no user-facing notice, consent prompt, or data handling warning. If users supply sensitive document content, this can cause unintended disclosure of confidential or regulated information to a third party.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The TTS voice is fixed to zh-CN-YunxiNeural, which enforces a specific language/locale behavior. There is no opt-in, language selection option, or justification that this skill is intentionally limited to a Chinese-language context.

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/make_video.py (reported line 19)May include surrounding context.

python
def generate_tts(text, output_mp3):
    """生成 TTS 语音"""
    cmd = [TTS_PY, "-m", "edge_tts", "--voice", "zh-CN-YunxiNeural", "--text", text, "--write-media", output_mp3]
    subprocess.run(cmd, check=True)
    return output_mp3

def generate_cover(prompt, output_image):

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/make_video.py (reported line 45)May include surrounding context.

python
def generate_tts(text, output_mp3):
    """生成 TTS 语音"""
    cmd = [TTS_PY, "-m", "edge_tts", "--voice", "zh-CN-YunxiNeural", "--text", text, "--write-media", output_mp3]
    subprocess.run(cmd, check=True)
    return output_mp3

def generate_cover(prompt, output_image):

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The background image prompt is transmitted to pollinations.ai over the network without explicit disclosure to the user. Prompts can contain confidential project details, personal data, or business-sensitive themes, so silent transmission creates a real privacy and data governance risk in this skill context.

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/make_video.py (reported line 32)May include surrounding context.

python
except Exception as e:
        print(f"生图失败,使用默认背景: {e}")
        # 如果生图失败,用 ffmpeg 生成纯色背景
        subprocess.run([FFMPEG, "-f", "lavfi", "-i", "color=c=#667eea:s=720x1280:d=1", "-frames:v", "1", output_image])
    return output_image

def make_video(audio_path, image_path, output_video):

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The natural-language instructions and examples are entirely Chinese and present the skill as operating in that locale, but they do not state that this is region-specific or offer users a language choice. Under SQP-3, forced language or locale without opt-in can be a policy concern.

Content

No source excerpt is available for this finding.