Back to skill

Security audit

Book Video Maker

Security checks for vulnerabilities and agentic risk

Overview

This video-generator skill mostly matches its stated purpose, but it automatically installs unpinned packages and handles API credentials with broader local file searching than users may expect.

Review this skill before installing. Use it only in an isolated environment, preinstall reviewed dependency versions yourself, provide a dedicated low-privilege Ark API key, avoid storing unrelated secrets in the searched markdown files, and treat quote JSON/book/author inputs as trusted until FFmpeg escaping is hardened.

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

Warning
Location
scripts/generate.py:26
Finding

Automatic Installation of Unpinned Python Dependencies

Content
View full analysis
Remediation
View remediation
--hash=sha256: requests== --hash=sha256: ``` The application should fail with a clear dependency error instead of invoking `pip` automatically. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate.py:161
Finding

User-Controlled FFmpeg Filtergraph Injection

Content
View full analysis
str: return text.replace("'", "").replace(":", "").replace("\\", "") def create_video(run_dir: Path, bg_paths: list, voice_path: Path, timestamps: list, segments: list, book_title: str, book_author: str): print(f"\n[3/4] 生成视频片段...") cn_font = get_font_path("msyhbd.ttc") en_font = get_font_path("arial.ttf") videos = [] random.seed(42) directions = [] for i in range(len(segments)): if i == 0: directions.append(random.randint(0, 3)) else: d = random.randint(0, 3) while d == directions[-1]: d = random.randint(0, 3) directions.append(d) for i, seg in enumerate(segments): dur = timestamps[i]["duration"] cn_c = escape_text(seg["cn"]) en_c = escape_text(seg.get("en", "")) out = run_dir / f"seg_{i}.mp4" bg = bg_paths[i % len(bg_paths)] cn_f = f"drawtext=text='{cn_c}':fontfile={cn_font}:fontsize=52:fontcolor=white:x=(w-text_w)/2:y=(h*7/10):shadowx=4:shadowy=4:shadowcolor=black@0.7" en_f = f"drawtext=text='{en_c}':fontfile={en_font}:fontsize=36:fontcolor=white:x=(w-text_w)/2:y=(h*7/10)+65:shadowx=3:shadowy=3:shadowcolor=black@0.6" title_f = f"drawtext=text='《{book_title}》':fontfile={cn_font}:fontsize=84:fontcolor=0x87CEEB:x=(w-text_w)/2:y=(h*3/10):shadowx=4:shadowy=4:shadowcolor=black@0.7,drawtext=text='作者:{book_author}':fontfile={cn_font}:fontsize=48:fontcolor=0xFFA500:x=(w-text_w)/2:y=(h*3/10)+80:shadowx=3:shadowy=3:shadowcolor=black@0.6" d = directions[i] if d == 0: vf = f"scale=1188:2112,crop=1080:1920:t*60:100,{title_f},{cn_f},{en_f}" elif d == 1: vf = f"scale=1188:2112,crop=1 ...[truncated 2976 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (21)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/generate.py (reported line 85)May include surrounding context.

python
payload = {"model": ARK_MODEL, "prompt": prompt, "size": "1080x1920", "response_format": "url", "watermark": False}
    
    try:
        r = requests.post(ARK_API_URL, headers=headers, json=payload, timeout=120)
        if r.status_code == 200:
            img_url = r.json()["data"][0]["url"]
            img_r = requests.get(img_url, timeout=30)

Unvalidated Output Injection

High
Category
Output Handling
Confidence
95% confidence
Finding

Model output is used without validation or sanitization. Unvalidated output injected into downstream contexts (SQL, shell, HTML) enables injection attacks and arbitrary code execution.

Content

Scanner excerpt · scripts/generate.py (reported line 112)May include surrounding context.

python
print(f"    [OK]")
        else:
            print(f"    [FAIL] 占位图")
            subprocess.run(["ffmpeg", "-y", "-f", "lavfi", "-i", "color=c=gray:s=1080x1920:d=1", "-frames:v", "1", str(output)], capture_output=True)
            paths.append(output)
        time.sleep(1)
    return paths

Unvalidated Output Injection

High
Category
Output Handling
Confidence
95% confidence
Finding

Model output is used without validation or sanitization. Unvalidated output injected into downstream contexts (SQL, shell, HTML) enables injection attacks and arbitrary code execution.

Content

Scanner excerpt · scripts/generate.py (reported line 219)May include surrounding context.

python
subprocess.run(["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", str(concat), "-c", "copy", str(merged)], capture_output=True)
    
    output = run_dir / "final.mp4"
    subprocess.run(["ffmpeg", "-y", "-i", str(merged), "-i", str(voice_path), "-c:v", "copy", "-c:a", "aac", "-b:a", "192k", "-shortest", str(output)], capture_output=True)
    return output

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The natural-language content describing setup, parameters, and behavior is presented only in Chinese, which effectively forces a specific language on users. The file does not offer an alternative language, opt-in, or explain that the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file's natural-language strings and configuration are centered on Chinese output, including the default voice zh-CN-YunxiNeural and hard-coded Chinese content generation, with no option presented for alternate language or locale behavior. This constitutes a language/locale policy concern because the skill enforces a specific language without user opt-in or documented justification.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Runtime auto-installation gives the script package-management capability that is broader than necessary for ordinary video generation and can execute unreviewed setup/install hooks. This is especially risky in agent or skill environments where users may not expect code to modify the Python environment or pull remote code.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Executing pip automatically and silently changes the environment and can run remote package code without consent. That is dangerous operationally and from a supply-chain perspective, especially when embedded in an agent skill that appears to only generate videos.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

Automatically running pip install at script startup executes package-management actions and arbitrary package code without user consent. In a skill context, this expands the trust boundary to PyPI and can lead to supply-chain compromise or unexpected code execution during installation.

Content

Scanner excerpt · scripts/generate.py (reported line 26)May include surrounding context.

python
import edge_tts
    import requests
except ImportError:
    subprocess.check_call([sys.executable, "-m", "pip", "install", "edge-tts", "requests", "-q"])
    import edge_tts
    import requests

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script searches multiple local markdown files for API keys, including oddly named files unrelated to the visible task, expanding its access to local secrets beyond what users would reasonably expect. In a skill setting, silent credential discovery from arbitrary workspace files materially increases the risk of unintended secret harvesting.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script reads API keys from environment variables and local files without clear disclosure, creating a secret-access behavior that may surprise users and administrators. Hidden secret collection is dangerous because it erodes informed consent and can expose credentials from files unrelated to this script's stated purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script transmits prompts and bearer credentials to an external image-generation service without an explicit user-facing warning. In a skill context, undisclosed external transmission is risky because prompts, metadata, and authorization tokens leave the local environment and may be retained by third parties.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/generate.py (reported line 85)May include surrounding context.

python
payload = {"model": ARK_MODEL, "prompt": prompt, "size": "1080x1920", "response_format": "url", "watermark": False}
    
    try:
        r = requests.post(ARK_API_URL, headers=headers, json=payload, timeout=120)
        if r.status_code == 200:
            img_url = r.json()["data"][0]["url"]
            img_r = requests.get(img_url, timeout=30)

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

Medium
Category
Data Flow
Confidence
86% confidence
Finding

The script fetches a second URL taken directly from the remote API response without validating the hostname, scheme, or destination. If the upstream service is compromised or returns attacker-controlled URLs, this becomes a server-side request forgery style primitive that can contact unexpected internal or external resources.

Content

Scanner excerpt · scripts/generate.py (reported line 88)May include surrounding context.

python
r = requests.post(ARK_API_URL, headers=headers, json=payload, timeout=120)
        if r.status_code == 200:
            img_url = r.json()["data"][0]["url"]
            img_r = requests.get(img_url, timeout=30)
            if img_r.status_code == 200 and len(img_r.content) > 10000:
                Path(output_path).parent.mkdir(parents=True, exist_ok=True)
                with open(output_path, "wb") as f:

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

python
print(f"    [OK]")
        else:
            print(f"    [FAIL] 占位图")
            subprocess.run(["ffmpeg", "-y", "-f", "lavfi", "-i", "color=c=gray:s=1080x1920:d=1", "-frames:v", "1", str(output)], capture_output=True)
            paths.append(output)
        time.sleep(1)
    return paths

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

python
for c in chunks:
                f.write(c)
        
        probe = subprocess.run(["ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", str(vf)], capture_output=True, text=True, encoding='utf-8', errors='ignore')
        try:
            dur = float(json.loads(probe.stdout)["format"]["duration"])
        except:

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

python
with open(concat, "w", encoding="utf-8") as f:
        for vf in all_files:
            f.write(f"file '{str(vf.absolute()).replace(chr(92), '/')}'\n")
    subprocess.run(["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", str(concat), "-c", "copy", str(merged)], capture_output=True)
    
    print(f"  总时长: {timestamps[-1]['end']:.2f}s")
    return merged, timestamps

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

python
with open(concat, "w", encoding="utf-8") as f:
        for vf in all_files:
            f.write(f"file '{str(vf.absolute()).replace(chr(92), '/')}'\n")
    subprocess.run(["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", str(concat), "-c", "copy", str(merged)], capture_output=True)
    
    print(f"  总时长: {timestamps[-1]['end']:.2f}s")
    return merged, timestamps

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

The ffmpeg filter graph is constructed by interpolating user-controlled book title, author, and quote text into the -vf argument with only partial escaping. That can break filter parsing or inject unintended ffmpeg filter syntax, causing command misuse, malformed output, or processing of unintended resources inside ffmpeg.

Content

Scanner excerpt · scripts/generate.py (reported line 204)May include surrounding context.

python
else:
            vf = f"scale=1188:2112,crop=1080:1920:50:192-t*60,{title_f},{cn_f},{en_f}"
        
        subprocess.run(["ffmpeg", "-y", "-loop", "1", "-i", str(bg), "-t", str(dur), "-vf", vf, "-c:v", "libx264", "-pix_fmt", "yuv420p", "-r", "30", str(out)], capture_output=True)
        if out.exists() and out.stat().st_size > 1000:
            videos.append(out)
        print(f"  [{i+1}/{len(segments)}] {dur:.2f}s")

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

python
subprocess.run(["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", str(concat), "-c", "copy", str(merged)], capture_output=True)
    
    output = run_dir / "final.mp4"
    subprocess.run(["ffmpeg", "-y", "-i", str(merged), "-i", str(voice_path), "-c:v", "copy", "-c:a", "aac", "-b:a", "192k", "-shortest", str(output)], capture_output=True)
    return output

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The description is presented only in Chinese ("书单爆款短视频生成器"), which imposes a specific language on users without any opt-in or indication that the skill is intentionally region-specific. This is a natural-language locale policy concern because the file provides no alternative language option or justification for the restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

Each entry includes a Chinese primary text field (cn) and the file presents the script as fixed bilingual content rather than offering language selection or opt-in. This can violate language/locale policy when a skill defaults to a specific language without giving the user a choice or stating that the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.