Back to skill

Security audit

Pipixia Drama Producer

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its stated video/TTS/Feishu workflow, but unsafe script handling of media filenames, temporary files, and credentials makes it risky enough for review before installation.

Install only in a restricted workspace with a low-privilege account, Feishu app credentials limited to the intended chat/actions, and explicit operator confirmation before any send_video.sh or send_audio.sh call. Avoid processing media paths from untrusted parties until send_video.sh is fixed to pass values as Python arguments instead of interpolating them into python3 -c, and replace shared /tmp paths with mktemp-based private directories.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/send_video.sh:47
Finding

Python Source Injection Through Untrusted Video Path Interpolation

Content
View full analysis
/dev/null || echo 0) ``` ### Technical Analysis The script embeds `FFPROBE_BIN` and `VIDEO_FILE` directly into a dynamically constructed Python program. Shell quoting of `"$VIDEO_FILE"` when assigning the variable does not make the value safe for later insertion into Python source code. A video filename containing quotes and Python syntax can terminate the intended Python string, close the `subprocess.run` invocation, and append attacker-controlled statements. The resulting code is passed to `python3 -c` and runs with the same privileges and environment as the Skill. Using an argument-array form for the eventual FFprobe operation does not mitigate this issue because injection occurs while constructing the surrounding Python source, before `subprocess.run` receives its arguments. The `FFPROBE` environment value is interpolated through the same unsafe mechanism. Although controlling the execution environment may already provide significant influence, it should still be treated as data rather than executable Python syntax. ### Attack Path 1. An attacker supplies, uploads, or causes the workflow to process a video with a filename containing crafted Python syntax. 2. The Skill invokes `send_video.sh` with the attacker-controlled path as `VIDEO_FILE`. 3. The script successfully uploads the file or proceeds to duration processing. 4. Lines 48–52 insert the malicious filename into the body of the `python3 ...[truncated 1284 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_audio.sh:16
Finding

Predictable Temporary Audio Path Permits Symlink File Clobbering

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:57
Finding

Fixed Shared Concat File Path Permits Symlink Clobbering

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

代码行为与声明的范围存在明显不一致。脚本 mix_audio.py 的核心功能是:获取视频时长、解析形如“起始时间:音频文件”的配音片段、对各音频做延时、可选加入循环 BGM,然后用 ffmpeg 将这些音频混合为一条输出音轨,并与原视频流复用输出。它不生成视频镜头,不做图生视频,不进行实际的视频剪辑或规范化处理,不执行 TTS 合成,也不包含任何飞书发送逻辑。因此,若将这段代码视为该技能的实现,其实际能力只是整个声明流程中的一个局部步骤,不能准确代表“全流程制作并发布”的声明。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The supplied code chunk only handles one limited part of the declared workflow: video normalization and start trimming via ffmpeg. It does not generate new shots, create video from images, produce dubbing, mix background music, or publish content to Feishu groups. This is a material description-to-behavior mismatch because the declared purpose presents a complete end-to-end short-drama production and distribution skill, while the actual code implements only a small preprocessing/editing utility.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied code implements only a narrow subset of the declared functionality: TTS generation and Feishu audio-message delivery. It does not perform image-to-video generation, video clipping/editing, ffmpeg normalization, BGM mixing, or broader short-drama assembly. While sending audio to Feishu is consistent with part of the description, the declared purpose presents this as a comprehensive end-to-end short-drama production skill, which this code chunk does not substantiate. Therefore the description materially overstates the behavior of the provided code.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/send_audio.sh (reported line 26)May include surrounding context.

sh
$TTS -t "$TEXT" -f "$TMP_AUDIO" -v "$VOICE" -l zh-CN

TOKEN=$(curl -sf -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
  -H "Content-Type: application/json" \
  -d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" | python3 -c "import sys,json; print(json.load(sys.stdin)['tenant_access_token'])")

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/send_audio.sh (reported line 30)May include surrounding context.

sh
-H "Content-Type: application/json" \
  -d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" | python3 -c "import sys,json; print(json.load(sys.stdin)['tenant_access_token'])")

FILE_KEY=$(curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/files" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file_type=opus" \
  -F "file_name=voice.mp3" \

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/send_audio.sh (reported line 36)May include surrounding context.

sh
-F "file_name=voice.mp3" \
  -F "file=@${TMP_AUDIO};type=audio/mpeg" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('data',{}).get('file_key','ERR'))")

curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"receive_id\":\"$CHAT_ID\",\"msg_type\":\"audio\",\"content\":\"{\\\"file_key\\\":\\\"$FILE_KEY\\\"}\"}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('✅ Sent:', d.get('data',{}).get('message_id','?'))"

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/send_video.sh (reported line 55)May include surrounding context.

sh
-F "file_name=voice.mp3" \
  -F "file=@${TMP_AUDIO};type=audio/mpeg" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('data',{}).get('file_key','ERR'))")

curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"receive_id\":\"$CHAT_ID\",\"msg_type\":\"audio\",\"content\":\"{\\\"file_key\\\":\\\"$FILE_KEY\\\"}\"}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('✅ Sent:', d.get('data',{}).get('message_id','?'))"

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/send_video.sh (reported line 27)May include surrounding context.

sh
APP_SECRET="${FEISHU_APP_SECRET:?Error: FEISHU_APP_SECRET not set}"

echo "🔑 Getting token..."
TOKEN=$(curl -sf -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
  -H "Content-Type: application/json" \
  -d "{\"app_id\": \"$APP_ID\", \"app_secret\": \"$APP_SECRET\"}" | python3 -c "import sys,json; print(json.load(sys.stdin)['tenant_access_token'])")

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/send_video.sh (reported line 32)May include surrounding context.

sh
-d "{\"app_id\": \"$APP_ID\", \"app_secret\": \"$APP_SECRET\"}" | python3 -c "import sys,json; print(json.load(sys.stdin)['tenant_access_token'])")

echo "🖼️  Uploading cover..."
IMAGE_KEY=$(curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/images" \
  -H "Authorization: Bearer $TOKEN" \
  -F "image_type=message" \
  -F "image=@${COVER_FILE}" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('data',{}).get('image_key','ERR'))")

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/send_video.sh (reported line 39)May include surrounding context.

sh
echo "   image_key: $IMAGE_KEY"

echo "📹 Uploading video ($(basename $VIDEO_FILE))..."
FILE_KEY=$(curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/files" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file_type=mp4" \
  -F "file_name=$(basename $VIDEO_FILE)" \

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill invokes shell commands and depends on environment-provided credentials and binaries, but it does not declare any tool scope or permission boundaries. In practice this widens the execution surface, making it easier for an agent runtime to grant broader shell/env access than users expect, which can lead to unintended command execution or access to sensitive environment variables such as Feishu app secrets.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill includes instructions to send generated video or audio to a Feishu group using application credentials, but it does not require an explicit user confirmation or present a transmission warning before publishing. In an agent setting, this creates a real risk of unintended data exfiltration or accidental posting of sensitive media to the wrong chat, especially because publication is the final step of an otherwise local workflow.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file specifies only zh-CN voices and the sample TTS command hard-codes -l zh-CN, which imposes a specific language/locale. There is no indication that users may opt into another language or that this is a region-specific requirement, so it conflicts with the language/locale policy criteria.

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

python
FFPROBE = os.environ.get("FFPROBE", "ffprobe")

def get_duration(f):
    r = subprocess.run([FFPROBE, "-v", "quiet", "-show_entries", "format=duration",
                        "-of", "csv=p=0", f], capture_output=True, text=True)
    return float(r.stdout.strip())

Tainted flow: 'FFPROBE' from os.environ.get (line 16, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
96% confidence
Finding

The executable name for ffprobe is taken from the FFPROBE environment variable and then executed. If an attacker can influence the environment in which this skill runs, they can replace ffprobe with an arbitrary program and achieve code execution under the skill's privileges; this is more dangerous here because the skill is designed for automated media workflows and likely runs unattended.

Content

Scanner excerpt · scripts/mix_audio.py (reported line 19)May include surrounding context.

python
FFPROBE = os.environ.get("FFPROBE", "ffprobe")

def get_duration(f):
    r = subprocess.run([FFPROBE, "-v", "quiet", "-show_entries", "format=duration",
                        "-of", "csv=p=0", f], capture_output=True, text=True)
    return float(r.stdout.strip())

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

python
"-shortest", args.output
    ]

    r = subprocess.run(cmd, capture_output=True, text=True)
    if r.returncode == 0:
        print(f"✓ Output: {args.output}")
    else:

Tainted flow: 'cmd' from os.environ.get (line 71, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
96% confidence
Finding

The ffmpeg executable is controlled by the FFMPEG environment variable and later executed via subprocess.run. An attacker who can set or poison that environment variable can cause arbitrary code execution, and in this skill context that could compromise the host used to generate, mix, and distribute media to collaboration channels.

Content

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

python
"-shortest", args.output
    ]

    r = subprocess.run(cmd, capture_output=True, text=True)
    if r.returncode == 0:
        print(f"✓ Output: {args.output}")
    else:

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

python
"-c:v", "libx264", "-crf", "22", "-preset", "fast",
            "-c:a", "aac", "-ar", "44100", "-ac", "2",
            norm_out]
    r1 = subprocess.run(cmd1, capture_output=True, text=True)
    if r1.returncode != 0:
        print("✗ Normalize failed:", r1.stderr[-300:])
        sys.exit(1)

Tainted flow: 'cmd1' from os.environ.get (line 29, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
88% confidence
Finding

The executable invoked by subprocess is taken from the FFMPEG environment variable without validation, so anyone who can influence the process environment can cause arbitrary code execution by pointing FFMPEG to a different binary or script. In an automation/agent environment that processes untrusted jobs, this expands the trust boundary from a known tool to attacker-controlled code.

Content

Scanner excerpt · scripts/normalize_and_trim.py (reported line 34)May include surrounding context.

python
"-c:v", "libx264", "-crf", "22", "-preset", "fast",
            "-c:a", "aac", "-ar", "44100", "-ac", "2",
            norm_out]
    r1 = subprocess.run(cmd1, capture_output=True, text=True)
    if r1.returncode != 0:
        print("✗ Normalize failed:", r1.stderr[-300:])
        sys.exit(1)

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

python
"-c:v", "libx264", "-crf", "22", "-preset", "fast",
            "-c:a", "aac", "-ar", "44100", "-ac", "2",
            args.output]
    r2 = subprocess.run(cmd2, capture_output=True, text=True)
    if r2.returncode != 0:
        print("✗ Trim failed:", r2.stderr[-300:])
        sys.exit(1)

Tainted flow: 'cmd2' from os.environ.get (line 40, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
88% confidence
Finding

This second ffmpeg execution has the same issue: the command's executable comes from an untrusted environment variable and is executed directly. If an attacker can set or poison FFMPEG in the runtime environment, they can run arbitrary programs during the trim step with the privileges of the skill.

Content

Scanner excerpt · scripts/normalize_and_trim.py (reported line 45)May include surrounding context.

python
"-c:v", "libx264", "-crf", "22", "-preset", "fast",
            "-c:a", "aac", "-ar", "44100", "-ac", "2",
            args.output]
    r2 = subprocess.run(cmd2, capture_output=True, text=True)
    if r2.returncode != 0:
        print("✗ Trim failed:", r2.stderr[-300:])
        sys.exit(1)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script defaults to the zh-CN-YunxiaNeural voice and hard-codes the TTS language to zh-CN. This imposes a specific language/locale behavior without opt-in or documentation that the skill is intentionally limited to a Chinese-language use case.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This shell script generates audio from user-provided text and uploads it to Feishu, then sends it as a chat message via multiple HTTP requests. Although the file header states its purpose, there is no runtime disclosure, confirmation, or explicit warning that user text and generated audio will be sent to an external service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/send_audio.sh (reported line 26)May include surrounding context.

sh
$TTS -t "$TEXT" -f "$TMP_AUDIO" -v "$VOICE" -l zh-CN

TOKEN=$(curl -sf -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
  -H "Content-Type: application/json" \
  -d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" | python3 -c "import sys,json; print(json.load(sys.stdin)['tenant_access_token'])")

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/send_audio.sh (reported line 36)May include surrounding context.

sh
-F "file_name=voice.mp3" \
  -F "file=@${TMP_AUDIO};type=audio/mpeg" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('data',{}).get('file_key','ERR'))")

curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"receive_id\":\"$CHAT_ID\",\"msg_type\":\"audio\",\"content\":\"{\\\"file_key\\\":\\\"$FILE_KEY\\\"}\"}" | python3 -c "import sys,json; d=json.load(sys.stdin); print('✅ Sent:', d.get('data',{}).get('message_id','?'))"

Static analysis

No suspicious patterns detected.