Back to skill

Security audit

book-video-generator

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a legitimate book-video generator, but it asks for broad runtime authority and automatically installs unpinned packages during use.

Review before installing. Use a virtual environment or container, preinstall and pin dependencies instead of allowing automatic pip installs, provide only the API keys needed for the chosen provider, keep outputs inside a dedicated project directory, and set SD_WEBUI_URL only to a trusted local endpoint.

Vulnerability Patterns
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
f.write(f"file '{cf}'\n")

    no_subs = os.path.join(tmpdir, "no_subs.mp4")
    subprocess.run(
        [FFMPEG, "-y", "-f", "concat", "-safe", "0", "-i", concat_list,
         "-c", "copy", no_subs],
        capture_output=True, check=True,
Confidence
88% confidence
Finding
The concat demuxer input file is generated by writing raw clip paths into ffmpeg's concat list using single-quoted entries without escaping embedded quotes or special characters. A crafted filename containing quote characters or concat directives can break out of the intended file entry and inject additional ffmpeg concat instructions, causing unintended file reads or processing of attacker-chosen media.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if need_mix:
        # 先烧录字幕到临时文件,再混音
        subs_output = os.path.join(tmpdir, "with_subs.mp4")
        subprocess.run(
            [FFMPEG, "-y", "-i", no_subs, "-vf",
             f"subtitles='{ass_escaped}':force_style='{style}'",
             "-c:a", "copy", subs_output],
Confidence
92% confidence
Finding
The subtitles filter argument is built by interpolating a path and a style string into ffmpeg's filter expression. Although the code escapes backslashes and colons in the ASS path, the style string includes a FontName derived from local system font enumeration and is not escaped for ffmpeg filter syntax; a font family containing special characters such as quotes, commas, or colons can break the filter argument and inject unintended filter options or additional parsing behavior.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
)
    else:
        # 无混音,直接烧录字幕到最终输出
        subprocess.run(
            [FFMPEG, "-y", "-i", no_subs, "-vf",
             f"subtitles='{ass_escaped}':force_style='{style}'",
             "-c:a", "copy", output_path],
Confidence
92% confidence
Finding
This is the same ffmpeg subtitles filter construction issue as above, but on the no-mix output path. An attacker-influenced font family name or other unescaped filter component can corrupt the filter graph and potentially coerce ffmpeg into unintended file access or processing behavior.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
import edge_tts
    except ImportError:
        print("正在安装 edge-tts...")
        os.system(f"{sys.executable} -m pip install edge-tts -q")
        import edge_tts

    os.makedirs(os.path.dirname(output_path) or ".", exist_ok=True)
Confidence
90% confidence
Finding
The script automatically executes a shell command to install a missing dependency at runtime using os.system(). Even though the command string is mostly fixed, invoking a shell from application code is risky because it performs unsolicited code installation/execution from external package sources and inherits the current environment and PATH, which increases supply-chain and execution risk in agent environments.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
image_data = img_resp.read()
    except Exception:
        import subprocess
        subprocess.check_call(
            ["curl", "-s", "-L", "-o", output_path, "--max-time", "60", image_url],
            stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
        )
Confidence
91% confidence
Finding
The fallback to `curl` executes an external program using attacker-influenced values `output_path` and especially `image_url`. Although `shell=False` avoids classic shell injection, this still creates a command-execution boundary and can be abused for SSRF-style access to arbitrary URLs or unexpected local file writes if untrusted input controls destination paths.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
except ImportError:
        import subprocess
        print("正在安装 google-genai pillow...")
        subprocess.check_call(
            [sys.executable, "-m", "pip", "install", "google-genai", "pillow", "-q"],
            stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
        )
Confidence
97% confidence
Finding
Automatically installing packages at runtime with `pip` is a supply-chain risk and executes code from external package repositories during normal script operation. In a skill/agent context, this expands the trust boundary significantly and can lead to arbitrary code execution if dependencies are compromised or if an attacker influences package resolution.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
except ImportError:
            import subprocess
            print("正在安装 volcengine-python-sdk...")
            subprocess.check_call(
                [sys.executable, "-m", "pip", "install",
                 "volcengine-python-sdk[ark]", "httpx", "-q"],
                stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
Confidence
97% confidence
Finding
This code dynamically installs `volcengine-python-sdk[ark]` and `httpx` when imports fail, causing the script to execute untrusted package installation logic at runtime. That is dangerous in automated environments because dependency compromise, typo-squatting, or resolver manipulation can result in arbitrary code execution.

Tainted flow: 'req' from os.environ.get (line 389, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
}).encode()

    req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"}, method="POST")
    with urllib.request.urlopen(req) as resp:
        result = json.loads(resp.read())

    image_data = base64.b64decode(result["images"][0])
Confidence
83% confidence
Finding
Unlike the hosted APIs, this request target is derived from `SD_WEBUI_URL` and can point to an arbitrary host, so the script can be turned into an SSRF primitive or used to send prompts to unintended internal services. In agent environments with sensitive network reachability, allowing unvalidated environment-controlled URLs is more dangerous than ordinary vendor API calls.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill instructs the agent to use shell commands, read and write local files, access environment variables for API keys, and make network calls, yet it declares no permissions. This creates a trust and review gap: a host platform or user may treat the skill as low-privilege while it actually performs privileged operations, increasing the chance of unintended command execution, credential exposure, or filesystem modification during use.

Unvalidated Output Injection

High
Category
Output Handling
Content
image_data = img_resp.read()
    except Exception:
        import subprocess
        subprocess.check_call(
            ["curl", "-s", "-L", "-o", output_path, "--max-time", "60", image_url],
            stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
        )
Confidence
88% confidence
Finding
`output_path` is passed directly to `curl -o` without validation, so if an untrusted caller controls it the script can overwrite arbitrary writable files. In an agent skill that may process user-supplied paths or generated filenames, this can become a file-write primitive and combine with other weaknesses for broader compromise.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/generate_image.py:144