@@ -41,8 +41,32 @@ func isLinkedDir(f fs.FileInfo, path string) bool {
4141 return false
4242}
4343
44+ // sanitizeFilePath validates and sanitizes a file path before passing it to external commands.
45+ // It ensures the path is absolute, clean, and refers to an existing regular file,
46+ // preventing path traversal and command injection via shell metacharacters.
47+ func sanitizeFilePath (path string ) (string , error ) {
48+ cleaned := filepath .Clean (path )
49+ if ! filepath .IsAbs (cleaned ) {
50+ return "" , fmt .Errorf ("file path must be absolute: %s" , path )
51+ }
52+ info , err := os .Stat (cleaned )
53+ if err != nil {
54+ return "" , fmt .Errorf ("file path is not accessible: %w" , err )
55+ }
56+ if ! info .Mode ().IsRegular () {
57+ return "" , fmt .Errorf ("path is not a regular file: %s" , cleaned )
58+ }
59+ return cleaned , nil
60+ }
61+
4462// resizeImageToBufferWithFFmpegGo 使用 ffmpeg-go 调整图片大小并输出到内存缓冲区
4563func resizeImageToBufferWithFFmpegGo (inputFile string , width int , outputFormat string /* e.g., "image2pipe", "png_pipe", "mjpeg" */ ) (* bytes.Buffer , error ) {
64+ sanitized , err := sanitizeFilePath (inputFile )
65+ if err != nil {
66+ return nil , fmt .Errorf ("invalid input file path: %w" , err )
67+ }
68+ inputFile = sanitized
69+
4670 outBuffer := bytes .NewBuffer (nil )
4771
4872 // Determine codec based on desired output format for piping
@@ -124,6 +148,12 @@ func generateThumbnailWithImagingOptimized(imagePath string, targetWidth int, qu
124148
125149// Get the snapshot of the video
126150func (d * Local ) GetSnapshot (videoPath string ) (imgData * bytes.Buffer , err error ) {
151+ sanitized , err := sanitizeFilePath (videoPath )
152+ if err != nil {
153+ return nil , fmt .Errorf ("invalid video path: %w" , err )
154+ }
155+ videoPath = sanitized
156+
127157 // Run ffprobe to get the video duration
128158 jsonOutput , err := ffmpeg .Probe (videoPath )
129159 if err != nil {
0 commit comments