T09 · Insecure Skill Coding Practices
- Location
scripts/build_video.py:31- Finding
Shared, Unkeyed Build Cache Allows Cross-Job Content Reuse and Cache Poisoning
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a disclosed Chinese short-video generator that uses external media APIs and local video tools, with some coding hygiene risks but no evidence of hidden or malicious behavior.
Install only if you are comfortable sending video scripts, prompts, generated media, and API-authenticated requests to the named third-party services. Use a private per-job work directory instead of the default /tmp/video-poc in shared environments, avoid passing untrusted output paths or filenames, and do not use sensitive or regulated content unless your provider and Feishu handling policies allow it.
scripts/build_video.py:31Shared, Unkeyed Build Cache Allows Cross-Job Content Reuse and Cache Poisoning
scripts/bgm.py:129Caller-Controlled BGM Filename Allows Writes Outside the Intended Directory
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
try:
resp = requests.post(MINIMAX_API_URL, json=payload, headers=headers, timeout=500, proxies=PROXIES)
data = resp.json()
if data.get("base_resp", {}).get("status_code") != 0:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
# 下载音频
if verbose: print(f" 📥 下载 BGM...")
dl_resp = requests.get(audio_url, timeout=60, proxies=PROXIES)
if dl_resp.status_code != 200:
if verbose: print(f" ⚠️ 下载失败: HTTP {dl_resp.status_code}")
return None
声明描述的是一个端到端的对话式短视频制作 agent,核心能力包括脚本设计、人工确认和自动生成 MP4 视频;而给出的代码片段只覆盖了音频/BGM 子模块。它会读取本地 BGM、在无匹配时请求外部音乐生成服务、保存生成结果,并将语音与背景音乐混音,输出仍是音频文件而非视频。虽然 BGM 混音可以作为视频制作的辅助实现细节,但从该代码本身看,其实际行为与声明的主要用途不一致,且包含未在声明中体现的外部音乐生成与本地音频资源访问能力。
声明描述的是一个更高层的对话式视频创作代理:先根据用户想法设计脚本,再人工确认,再自动生成MP4,并暗示支持AI旁白、认知自述/播客风格、文稿转视频等复合流程。实际代码只是一个底层视频生成封装,功能集中在:签名请求火山引擎API、提交文生视频/图生视频任务、轮询状态、下载生成视频。它没有任何对话管理、脚本策划、人工确认、文本转旁白、音频合成、把文稿拆解成镜头脚本等逻辑。与此同时,代码确实具备未在声明中明确体现的外部API访问和凭证使用能力。虽然“自动制作MP4”与代码下载MP4部分相符,但整体主用途和能力边界与声明存在实质差异,因此应判定为不匹配。
声明描述的是一个端到端的短视频创作 agent,核心结果应是脚本规划并自动制作 MP4 视频;而实际代码只是一个 TTS 子模块,负责把脚本文本转成 MP3 音频并生成字幕时间轴。虽然 TTS 可作为视频制作的支撑环节,但该代码片段本身没有任何视频合成、画面生成、脚本策划、确认交互或 MP4 输出逻辑。此外,代码依赖环境变量并通过 WebSocket 访问外部火山播客 API,这种网络能力和外部资源使用在声明权限中也未体现。因此,代码实际行为与声明用途存在明显不匹配。
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
"piano": "minimal piano instrumental, 简洁, 干净, 留白, 沉稳, 无人声",
"corporate": "corporate tech instrumental, 商务, 科技感, 简洁现代, 无人声",
}
return prompts.get(style, f"instrumental background music, {style} style, 无人声")
def mix_audio_with_bgm(voice_path, output_path, bgm_path, volume=0.35,
The skill describes and instructs use of powerful capabilities including shell execution, filesystem access, environment-based secret use, and multiple networked APIs, but it does not declare any tool scope or allowed-tools boundary. That increases the chance an agent can invoke more capabilities than the user expects, making misuse or accidental overreach harder to constrain or audit.
The skill is described entirely as a Chinese short-video creation tool and the available voice options are all Chinese-language voices, with a Chinese default selected automatically. There is no indication that the user can opt into another language or that the Chinese-only constraint is a documented, justified regional limitation.
The skill routes user content to multiple third-party services for TTS, video generation, and music generation, yet it does not provide a clear privacy warning or consent boundary for those disclosures. Users may reasonably assume local processing, while their prompts, scripts, or derived media are actually sent to external providers and authenticated with stored credentials.
The skill states that completed MP4 files are sent through Feishu, but it does not prominently warn users that generated content leaves the local environment and is transmitted to an external service. If user scripts contain sensitive business, personal, or regulated content, this can cause unintended data disclosure.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def _convert_to_wav(audio_path, wav_path):
"""mp3 → 16kHz mono PCM wav(FunASR 要求)"""
subprocess.run([
"ffmpeg", "-y", "-i", audio_path,
"-ar", "16000", "-ac", "1", "-f", "wav",
wav_path
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
BGM_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "bgm")
# MiniMax API
MINIMAX_API_URL = "https://api.minimaxi.com/v1/music_generation"
MINIMAX_API_KEY = os.environ.get("MINIMAX_API_KEY", "")
# 代理配置(MiniMax API 需要代理访问)
The manifest describes an AI short-video creation workflow, but does not mention handling infrastructure configuration or credential retrieval from process environment variables. In this file, the code reads MINIMAX_API_KEY and proxy settings to contact an external provider, which is an additional capability beyond the stated user-facing purpose.
The function sends user- or model-derived prompt text to a third-party service without any visible consent, minimization, or warning in the code path. In a video-creation context, prompts may contain sensitive ideas, script fragments, names, or proprietary content, so silent external transmission creates a privacy and data-governance risk.
This line transmits prompt content and service metadata to an external provider. In this skill context, that behavior is functionally expected, but it is still security-relevant because it creates an external data-exfiltration path for potentially sensitive creative or user-provided content.
}
try:
resp = requests.post(MINIMAX_API_URL, json=payload, headers=headers, timeout=500, proxies=PROXIES)
data = resp.json()
if data.get("base_resp", {}).get("status_code") != 0:
The code blindly fetches audio_url returned by the upstream API without validating the scheme, host, or destination. If the API response is compromised or malicious, this can turn the skill into an SSRF primitive that makes arbitrary outbound requests through the host and any configured proxy.
# 下载音频
if verbose: print(f" 📥 下载 BGM...")
dl_resp = requests.get(audio_url, timeout=60, proxies=PROXIES)
if dl_resp.status_code != 200:
if verbose: print(f" ⚠️ 下载失败: HTTP {dl_resp.status_code}")
return None
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
if verbose:
print(f" 🎵 BGM 混音中 ({int(volume*100)}%)...")
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=500)
if result.returncode != 0:
if verbose:
print(f" ⚠️ ffmpeg 混音失败: {result.stderr[-200:]}")
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def _get_duration(path):
"""用 ffprobe 获取音频时长"""
try:
r = subprocess.run(
["ffprobe", "-i", path, "-show_entries", "format=duration",
"-v", "quiet", "-of", "csv=p=0"],
capture_output=True, text=True, timeout=10)
The default voice is fixed to a Chinese TTS speaker, and the surrounding CLI/help text also frames the tool entirely in Chinese. Under the policy, forcing a specific language or locale without user opt-in is a natural-language policy concern unless the restriction is clearly documented and justified as region-specific.
The code invokes ffmpeg and then replaces the original clip with the speed-adjusted output using os.replace, which is a file write/overwrite operation. While there is optional verbose logging after success, there is no unconditional user-facing warning, confirmation, or comment/docstring disclosure that the original file at clip_path will be modified in place.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
'-r', '24', '-an',
tmp_path
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
if result.returncode == 0 and os.path.exists(tmp_path):
os.replace(tmp_path, clip_path)
if verbose:
The manifest describes a short-video creation workflow but does not state that the skill will access host environment secrets. This code reads VOLC_ACCESS_KEY_ID and VOLC_SECRET_KEY and uses them to initialize JimengVideo, which adds a credential-access capability beyond the user-facing purpose described.
The file begins with a Chinese-only natural-language description, and all user-facing strings in the script are also Chinese. This indicates a fixed language/locale choice without any visible opt-in, selection mechanism, or documented region-specific justification, which matches the language/locale policy violation criteria.
The file title and user-facing strings are in Chinese, and the default voice is a Chinese voice variant, with no indication that users can choose locale or language as a policy-controlled preference. This can constitute a language/locale policy issue when the skill implicitly assumes one language without documenting opt-in or offering a choice.
The code accesses VOLC_APP_ID and VOLC_ACCESS_KEY from environment variables to authenticate with the external service. The file contains no explicit warning to users that credentials must be present and will be used for outbound authentication beyond an error message when missing.
No suspicious patterns detected.