T09 · Insecure Skill Coding Practices
- Location
images_to_video.py:25- Finding
Predictable Temporary Manifest Allows Local File Clobbering
- Content
View full analysis
Vulnerability Details
File Location:
images_to_video.py, lines 25-30 and 53-56
Vulnerability Type: Predictable temporary file, symlink following, and unsafe FFmpeg manifest construction
Risk Level: MediumVulnerable Code
python # Create temporary file list file_list_path = Path('filelist.txt') with open(file_list_path, 'w') as f: for img in image_files: duration = 1.0 / fps f.write(f"file '{Path(img).absolute()}'\n") f.write(f"duration {duration}\n") # FFmpeg command cmd = [ 'ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', str(file_list_path), '-vsync', 'vfr', '-pix_fmt', 'yuv420p', '-crf', str(crf), output_path ] try: result = subprocess.run(cmd, capture_output=True, text=True, check=True) print(f"✅ Video created: {output_path}") return output_path except subprocess.CalledProcessError as e: print(f"❌ FFmpeg error: {e.stderr}") sys.exit(1) finally: # Clean up temp file if file_list_path.exists(): file_list_path.unlink()Technical Analysis
The script uses the fixed filename
filelist.txtin the process's current working directory. It opens that path in write mode without exclusive creation and without checking whether it is a symbolic link. On platforms that follow symbolic links during file opening, an attacker with write access to the working directory can pre-createfilelist.txtas a symlink to another file writable by the victim. The subsequentopen(..., 'w')operation follows the link and truncates the target file.The
finallyblock then deletes the predictable path. In the symlink scenario, this normally deletes the symlink rather than the linked target, making the attack artifact less persistent while leaving the target corrupted.Image paths are also interpolated directly into FFmpeg concat-demuxer syntax. Filenames containing single quotes, carriage returns, or newline characters can alter the generated manife ...[truncated 1765 chars]
- Remediation
View remediation
Remediation Suggestions
- Create the manifest through Python's
tempfilemodule using exclusive, unpredictable file creation:
python import os import tempfile manifest_path = None try: with tempfile.NamedTemporaryFile( mode="w", encoding="utf-8", prefix="ai-video-", suffix=".ffconcat", delete=False ) as manifest: manifest_path = manifest.name for image in image_files: resolved = Path(image).resolve(strict=True) escaped = str(resolved).replace("'", "'\\''") manifest.write(f"file '{escaped}'\n") manifest.write(f"duration {1.0 / fps}\n") cmd = [ "ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", manifest_path, "-vsync", "vfr", "-pix_fmt", "yuv420p", "-crf", str(crf), output_path, ] subprocess.run(cmd, capture_output=True, text=True, check=True) finally: if manifest_path: Path(manifest_path).unlink(missing_ok=True)-
Apply FFmpeg concat-demuxer escaping rules to every filename. Reject filenames containing carriage returns or newline characters if robust escaping cannot be guaranteed.
-
Resolve and validate all input paths before writing the manifest. Require regular files where appropriate.
-
Avoid creating temporary state in the caller's working directory.
-
Preserve list-based
subprocess.runinvocation and do not introduceshell=True. -
Add tests covering symbolic links, concurrent executions, single quotes, newlines, and unusual Unicode filenames.
- Create the manifest through Python's
