T09 · Insecure Skill Coding Practices
- Location
scripts/render_from_timing_csv.py:68- Finding
FFconcat Directive Injection Through Crafted Image Filenames
- Content
View full analysis
Vulnerability Details
File Location:
scripts/render_from_timing_csv.py, lines 68–86
Vulnerability Type: FFconcat manifest injection
Risk Level: MediumVulnerable Code
python def write_ffconcat(images, timings, output: Path): lines = ["ffconcat version 1.0"] for image, row in zip(images, timings): lines.append(f"file '{image.resolve()}'") lines.append(f"duration {row['duration_sec']:.3f}") lines.append(f"file '{images[-1].resolve()}'") output.write_text("\n".join(lines) + "\n", encoding="utf-8") def run_ffmpeg(ffconcat_path: Path, audio_path: Path, output_path: Path, overwrite: bool): cmd = [ "ffmpeg", "-y" if overwrite else "-n", "-safe", "0", "-f", "concat",Technical Analysis
The script interpolates image paths directly into an FFconcat control file without escaping or rejecting FFconcat metacharacters. Unix filenames can contain single quotes, backslashes, and newline characters. A filename containing these characters can terminate the intended
filedirective and introduce additional directives into the generated manifest.Image discovery only verifies that each entry is a regular file whose final suffix is
.png,.jpg, or.jpeg. Therefore, an attacker can create a filename that contains injected content while still ending in an accepted extension.The manifest is subsequently processed using
ffmpeg -safe 0. This disables the concat demuxer's safe-path restrictions and may permit injected directives to reference absolute paths, paths outside the supplied image directory, or protocols supported by the installed FFmpeg build. Passing the FFmpeg command as an argument list prevents shell injection, but it does not prevent injection into the FFconcat file format.Attack Path
- An attacker gains the ability to supply a slide-image directory or place files in the directory s ...[truncated 1531 chars]
- Remediation
View remediation
Remediation Suggestions
- Do not place source filenames directly into an FFconcat control file.
- Stage or link accepted images into a private temporary directory using generated names such as
slide_0001.png, then reference only those generated names. - If original paths must be used, implement escaping that precisely follows FFconcat syntax and reject filenames containing carriage returns, newlines, null bytes, single quotes, or other control characters.
- Verify after resolution that every selected image remains directly within the intended image directory.
- Avoid
-safe 0where possible. Use safe relative paths from a controlled staging directory and retain FFmpeg's safe-path validation. - Create temporary manifests with restrictive permissions and unpredictable names, and remove them after rendering when persistent output is not requested.
- Add tests using filenames containing quotes, backslashes, newlines, spaces, and directive-like text to ensure each filename remains exactly one manifest entry.
