T09 · Insecure Skill Coding Practices
- Location
scripts/video_downloader.py:139- Finding
Unsafe Selection and Overwrite of Pre-existing Media Files
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a straightforward video-downloader skill, but users should choose output folders carefully and avoid untrusted URLs.
Install only if you are comfortable with a tool that fetches user-provided video URLs and writes media files locally. Use a fresh, private output directory for each download, avoid shared or untrusted folders, and do not use it for internal, localhost, or otherwise sensitive URLs.
scripts/video_downloader.py:139Unsafe Selection and Overwrite of Pre-existing Media Files
The skill advertises shell execution, file reads, and file writes via its described use of yt-dlp/ffmpeg and local output paths, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization gap: an agent may invoke broader capabilities than reviewers or policy expect, increasing the risk of unsafe command execution, arbitrary file access, or writes to unintended locations.
The manifest description and the entire user-facing documentation are written only in Chinese, with no indication that other languages are supported or that Chinese is required for a region-specific purpose. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.
The module docstring and all user-facing usage text are written only in Chinese, which imposes a specific language on users without opt-in. The policy explicitly flags language or locale constraints unless the skill offers a choice or documents a justified regional scope.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def has_audio_stream(filepath):
try:
result = subprocess.run(
['ffprobe', '-v', 'error', '-select_streams', 'a', '-show_entries', 'stream=codec_type', '-of', 'csv=p=0', filepath],
capture_output=True, text=True, timeout=10
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def has_video_stream(filepath):
try:
result = subprocess.run(
['ffprobe', '-v', 'error', '-select_streams', 'v', '-show_entries', 'stream=codec_type', '-of', 'csv=p=0', filepath],
capture_output=True, text=True, timeout=10
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
merged_path = os.path.join(output_dir, f'{base_name}_merged.mp4')
cmd = ['ffmpeg', '-i', video_path, '-i', other_file, '-c:v', 'copy', '-c:a', 'aac', '-map', '0:v:0', '-map', '1:a:0', merged_path]
try:
subprocess.run(cmd, check=True, capture_output=True, timeout=120)
if os.path.exists(merged_path):
print(f'合并完成: {merged_path}')
return merged_path
The script passes an untrusted user-supplied URL directly to yt-dlp, which can trigger outbound network access to arbitrary hosts and potentially internal services depending on the runtime environment. While this is not shell injection, it does create an SSRF-like/network pivot risk because the tool is explicitly a downloader and the skill context encourages fetching attacker-controlled URLs.
print('获取视频格式信息...')
list_cmd = ['yt-dlp', '-F', '--no-warnings', url]
try:
result = subprocess.run(list_cmd, capture_output=True, text=True, timeout=30, encoding='utf-8')
lines = result.stdout.splitlines()
except Exception as e:
raise Exception(f'获取格式列表失败: {e}')
This is the main yt-dlp download execution path and accepts an arbitrary user-controlled URL, causing the host to retrieve attacker-chosen remote content. In agent or server environments, that can be abused for SSRF-style access, bandwidth/disk exhaustion, or retrieval of hostile media/content via a trusted system.
url
]
try:
subprocess.run(download_cmd, check=True, timeout=600, capture_output=True, text=True, encoding='utf-8')
except subprocess.CalledProcessError as e:
raise Exception(f'下载失败: {e.stderr}')
files = [f for f in os.listdir(output_dir) if f.endswith(('.mp4', '.mkv', '.webm', '.mov', '.avi'))]