T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/add-subtitles.sh:41
- Finding
- FFmpeg Filtergraph Injection Through Unvalidated User-Controlled Parameters<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/add-subtitles.sh:41-42` - `scripts/crop.sh:58-59` - `scripts/resize.sh:53-58` - `scripts/speed.sh:45-51` **Vulnerability Type**: Injection into FFmpeg filtergraph syntax **Risk Level**: Medium ### Vulnerable Code ```bash # scripts/add-subtitles.sh:41-42 # Add subtitles (burn into video) ffmpeg -i "$INPUT" -vf "subtitles='$SUBTITLES'" -c:a copy "$OUTPUT" ``` ```bash # scripts/crop.sh:58-59 # Crop video ffmpeg -i "$INPUT" -vf "crop=$WIDTH:$HEIGHT:$X:$Y" -c:a copy "$OUTPUT" ``` ```bash # scripts/resize.sh:53-58 if [[ -n "$SCALE" ]]; then # Scale proportionally to height ffmpeg -i "$INPUT" -vf "scale=-2:$SCALE" -c:a copy "$OUTPUT" elif [[ -n "$WIDTH" ]] && [[ -n "$HEIGHT" ]]; then # Exact dimensions ffmpeg -i "$INPUT" -vf "scale=$WIDTH:$HEIGHT" -c:a copy "$OUTPUT" ``` ```bash # scripts/speed.sh:45-51 # Adjust speed using setpts for video and atempo for audio # atempo only works between 0.5 and 2.0, so we may need to chain filters if (( $(echo "$RATE >= 0.5 && $RATE <= 2.0" | bc -l) )); then ffmpeg -i "$INPUT" -filter_complex "[0:v]setpts=PTS/$RATE[v];[0:a]atempo=$RATE[a]" -map "[v]" -map "[a]" "$OUTPUT" else echo "Warning: Speed rate outside 0.5-2.0 range may require multiple filter passes" ffmpeg -i "$INPUT" -filter_complex "[0:v]setpts=PTS/$RATE[v]" -map "[v]" -an "$OUTPUT" fi ``` ### Technical Analysis The scripts interpolate user-controlled subtitle paths, crop coordinates, dimensions, scale values, and speed rates directly into FFmpeg filter expressions. Shell quoting prevents these values from being split into separate shell arguments, so this is not ordinary shell-command injection. However, shell quoting does not escape FFmpeg's independent filtergraph grammar. Characters meaningful to FFmpeg—including quotes, commas, semicolons, brackets, colons, and backslashes—can change how the resulting filter expression is parsed. The numeric options are only checked for being non ...[truncated 1829 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Apply strict, anchored validation to every numeric filter parameter: - Width, height, scale, and crop coordinates should accept only integers in defined ranges. - Speed should accept only a positive decimal number within a supported range. - Reject all syntax delimiters rather than relying on FFmpeg to reject malformed expressions. 2. Example integer validation: ```bash if [[ ! "$WIDTH" =~ ^[1-9][0-9]*$ ]] || [[ ! "$HEIGHT" =~ ^[1-9][0-9]*$ ]] || [[ ! "$X" =~ ^[0-9]+$ ]] || [[ ! "$Y" =~ ^[0-9]+$ ]]; then echo "Error: invalid crop dimensions or coordinates" >&2 exit 1 fi ``` 3. Validate speed as a positive decimal and enforce the range supported by the selected audio-filter construction: ```bash if [[ ! "$RATE" =~ ^([0-9]+([.][0-9]+)?|[.][0-9]+)$ ]]; then echo "Error: invalid speed rate" >&2 exit 1 fi ``` 4. Escape subtitle paths according to FFmpeg filter-expression rules. Account for backslashes, colons, apostrophes, commas, and other filtergraph metacharacters. Do not assume shell quoting provides FFmpeg escaping. 5. Prefer generating a controlled filter script or using an implementation that separates validated parameter values from filtergraph structure. 6. Where operationally possible, explicitly restrict the protocols FFmpeg may use and run media processing in a sandbox with: - Minimal filesystem access. - No unnecessary network access. - CPU, memory, file-size, and execution-time limits. - A dedicated low-privilege account. ]]>
