Back to skill

Security audit

AI重生复仇爽文自动生成

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated video-generation purpose, but it needs review because it can execute unsafe shell commands from media filenames and sends story text to a hardcoded third-party TTS service without clear disclosure.

Review before installing. Use this only in an isolated workspace with trusted media files, do not place confidential text in output.txt, and assume story text may be sent both to the configured OpenAI-compatible endpoint and to the hardcoded TTS service. The package should be fixed to remove shell=True, validate media filenames, make the TTS endpoint configurable and disclosed, and require an explicit preflight confirmation before running the full pipeline.

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
pipeline.py:263
Finding

Undisclosed Transmission of Story Content to a Hardcoded Third-Party TTS Service

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
pipeline.py:173
Finding

Arbitrary Command Execution Through Shell-Interpreted Video Filenames

Content
View full analysis
float: cmd = f'ffprobe -v error -show_entries format=duration -of csv=p=0 "{file}"' return float(subprocess.check_output(cmd, shell=True).decode().strip()) ``` ```python def _build_video_list(target_duration: float): videos = [v for v in os.listdir(VIDEO_DIR) if v.endswith(".mp4")] if not videos: raise FileNotFoundError(f"{VIDEO_DIR}/ 下没有 .mp4 文件") total = 0.0 with open(VIDEO_LIST, "w", encoding="utf-8") as f: while total < target_duration: v = random.choice(videos) path = os.path.join(VIDEO_DIR, v) dur = _get_duration(path) total += dur f.write(f"file '{path}'\n") ``` ### Technical Analysis `_build_video_list()` enumerates filenames from the user-controlled `video/` directory and passes each selected path to `_get_duration()`. `_get_duration()` interpolates that path into a command string and executes it with `shell=True`. Wrapping the filename in double quotes does not make this safe. POSIX shells still perform command substitution such as `$(command)` and backtick substitution inside double-quoted strings. A filename containing shell metacharacters can therefore cause the shell to execute attacker-selected commands before `ffprobe` runs. For example, a valid filename ending in `.mp4` can include a command substitution expression. When the corresponding file is randomly selected, construction of the `ffprobe` command embeds that expression inside double quotes, and the shell evaluates it. The generic `_run_cmd()` function also executes command strings through a shell. Its currently observed callers primarily construct commands from f ...[truncated 2082 chars]
Remediation
View remediation
float: result = subprocess.check_output( [ "ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0", file, ], text=True, ) return float(result.strip()) ``` Apply the same rule to all FFmpeg invocations. Replace `_run_cmd(cmd: str)` with a helper that accepts only a sequence of arguments: ```python def _run_cmd(args): log(" $ " + " ".join(repr(arg) for arg in args)) subprocess.run(args, check=True) ``` Additional hardening should include: 1. Validate asset filenames and reject control characters or unexpected path components. 2. Resolve asset paths and verify that they remain under the intended `video/` directory. 3. Safely encode or escape filenames written to FFmpeg concat manifest files; shell removal alone does not address concat-demuxer parsing. 4. Avoid constructing FFmpeg filter expressions from unbounded strings. Validate volume arguments against reasonable numeric ranges. 5. Run media processing with a minimally privileged account and a restricted environment. 6. Treat externally supplied media archives and filenames as untrusted input. 7. Add regression tests using filenames containing spaces, quotes, dollar signs, backticks, semicolons, and newline characters. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (20)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

Using subprocess.run with shell=True on dynamically composed command text is a classic tool-parameter abuse issue. In this pipeline, ffmpeg commands are assembled from runtime state and local file references, so a malicious filename or unexpected input can alter command semantics and execute arbitrary shell commands.

Content

Scanner excerpt · pipeline.py (reported line 175)May include surrounding context.

python
def _run_cmd(cmd: str):
    log(f"  $ {cmd}")
    subprocess.run(cmd, shell=True, check=True)


def _get_duration(file: str) -> float:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

subprocess.check_output with shell=True on a command string that embeds a file path allows attacker-controlled media names to abuse shell parsing. Because the skill consumes files from local directories, an attacker who can place or influence file names can potentially achieve arbitrary command execution.

Content

Scanner excerpt · pipeline.py (reported line 180)May include surrounding context.

python
def _get_duration(file: str) -> float:
    cmd = f'ffprobe -v error -show_entries format=duration -of csv=p=0 "{file}"'
    return float(subprocess.check_output(cmd, shell=True).decode().strip())


# ─────────────────────────────────────────────────────────────

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill describes capabilities that include environment-variable access, file read/write, network use, and shell execution, but it does not declare any explicit tool scope or permission boundaries. That omission increases the chance an agent will invoke powerful actions without user awareness or platform-level restriction, especially because the skill later instructs full pipeline execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger phrases are broad and natural-language, making accidental or overly eager activation more likely. In this skill, activation can lead to shell commands, file creation, and external API transmission, so loose triggering materially raises the risk of unintended execution.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 68)May include surrounding context.

macOS

brew install ffmpeg

Ubuntu / Debian

sudo apt install ffmpeg

Windows:下载后将 bin/ 加入系统 PATH

https://ffmpeg.org/download.html

text

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

The configuration explicitly supports sending prompts and generated story content to an external OpenAI-compatible endpoint. External transmission is expected for this workflow, but it is still security-relevant because user input and generated content leave the local environment and the skill does not pair this with strong disclosure or destination restrictions.

Content

Scanner excerpt · SKILL.md (reported line 83)May include surrounding context.

md
cfg = {
    # ── LLM ──────────────────────────────────
    "api_key":   "YOUR_OPENAI_COMPATIBLE_API_KEY",
    "base_url":  "https://api.example.com/v1",   # OpenAI 兼容端点
    "model":     "gpt-4o",

    # ── Prompt(可选,有内置默认值)──────────

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The environment-variable example reinforces use of an external API endpoint and encourages execution without emphasizing what data will be transmitted. This is not inherently malicious, but it contributes to a workflow where sensitive prompts or text could be sent off-device without adequate warning.

Content

Scanner excerpt · SKILL.md (reported line 122)May include surrounding context.

bash
export OPENAI_API_KEY="sk-xxx"
export OPENAI_BASE_URL="https://api.example.com/v1"
export OPENAI_MODEL="gpt-4o"
python pipeline.py --all --theme 修仙

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The Python invocation example again normalizes outbound transmission of generated content to an external service. In context, this is functional rather than covert, but it remains a true security concern because the skill lacks explicit safeguards around endpoint trust, user consent, and sensitive-content handling.

Content

Scanner excerpt · SKILL.md (reported line 134)May include surrounding context.

md
cfg = {
    "api_key":  "sk-xxx",
    "base_url": "https://api.example.com/v1",
    "model":    "gpt-4o",
}

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill instructs the agent to run python pipeline.py --all --theme <题材> directly and stream logs, but it does not require warning the user that local files will be created and that content may be sent to an external LLM API. This can cause unintended data transmission and code execution in the user's environment without meaningful informed consent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The operational instructions are written as a fixed behavior for handling Chinese-language requests and examples, but they do not offer the user a language or locale choice. This can amount to a language-policy issue when a skill implicitly constrains responses or workflow to a specific language without opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The prompts require Chinese-language generation, and the TTS configuration fixes a zh-CN voice, effectively forcing a specific language/locale. The file does not offer opt-in language selection or explain a necessary region-specific constraint.

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 · pipeline.py (reported line 114)May include surrounding context.

python
# 4. ffmpeg / ffprobe
    for tool in ("ffmpeg", "ffprobe"):
        try:
            subprocess.run([tool, "-version"], capture_output=True, check=True)
        except (FileNotFoundError, subprocess.CalledProcessError):
            errors.append(
                f"  ✗ 系统未找到 {tool}\n"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · pipeline.py (reported line 120)May include surrounding context.

python
f"  ✗ 系统未找到 {tool}\n"
                f"    → 请安装 FFmpeg:https://ffmpeg.org/download.html\n"
                f"      macOS:   brew install ffmpeg\n"
                f"      Ubuntu:  sudo apt install ffmpeg\n"
                f"      Windows: 下载后将 bin/ 目录加入 PATH"
            )

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · pipeline.py (reported line 163)May include surrounding context.

python
def _make_client(cfg: dict) -> OpenAI:
    api_key  = cfg.get("api_key")  or os.environ.get("OPENAI_API_KEY",  "")
    base_url = cfg.get("base_url") or os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1")
    if not api_key:
        raise ValueError("缺少 API Key:请在 cfg['api_key'] 或环境变量 OPENAI_API_KEY 中提供")
    return OpenAI(api_key=api_key, base_url=base_url)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · pipeline.py (reported line 413)May include surrounding context.

python
def _make_client(cfg: dict) -> OpenAI:
    api_key  = cfg.get("api_key")  or os.environ.get("OPENAI_API_KEY",  "")
    base_url = cfg.get("base_url") or os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1")
    if not api_key:
        raise ValueError("缺少 API Key:请在 cfg['api_key'] 或环境变量 OPENAI_API_KEY 中提供")
    return OpenAI(api_key=api_key, base_url=base_url)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The shell execution capability in _run_cmd and _get_duration is broader than necessary for a video-generation pipeline and increases the attack surface substantially. Since this skill processes local media files and generated lists, unnecessary shell invocation creates a realistic path to host command execution from crafted inputs.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
96% confidence
Finding

_run_cmd executes a caller-supplied command string with shell=True, which enables shell metacharacter injection if any part of the command incorporates untrusted filenames or parameters. In this skill, that risk is real because command strings are built from filesystem-derived values and runtime options before being passed to ffmpeg via this helper.

Content

Scanner excerpt · pipeline.py (reported line 175)May include surrounding context.

python
def _run_cmd(cmd: str):
    log(f"  $ {cmd}")
    subprocess.run(cmd, shell=True, check=True)


def _get_duration(file: str) -> float:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

_get_duration constructs a shell command containing a file path and executes it with shell=True. Because file names can contain shell-significant characters, a crafted media filename in audio/ or video/ could break out of the quoted context and trigger arbitrary command execution on the host.

Content

Scanner excerpt · pipeline.py (reported line 180)May include surrounding context.

python
def _get_duration(file: str) -> float:
    cmd = f'ffprobe -v error -show_entries format=duration -of csv=p=0 "{file}"'
    return float(subprocess.check_output(cmd, shell=True).decode().strip())


# ─────────────────────────────────────────────────────────────

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill sends story text from output.txt to a third-party TTS endpoint without clear in-code consent, disclosure, or data-handling controls. If users place sensitive or proprietary text into the pipeline, that content is exfiltrated to an external service outside the local environment.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This requests.post call transmits generated text to an external TTS API. In the skill context, the content is user-influenced and may include sensitive material, so the outbound transfer is a real privacy and data-governance concern even if it is part of intended functionality.

Content

Scanner excerpt · pipeline.py (reported line 269)May include surrounding context.

python
def _call_tts(text: str, index: int):
    payload = {"text": text, **VOICE_CONFIG}
    r = requests.post(TTS_API_URL, json=payload, timeout=60)
    if r.status_code == 200:
        path = os.path.join(AUDIO_DIR, f"{index:03d}.mp3")
        with open(path, "wb") as f:

Static analysis

No suspicious patterns detected.