This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch release/6.1 in repository ffmpeg.
commit f5ea126b2751919179456ce4cad5eece7df86cd8 Author: Michael Niedermayer <[email protected]> AuthorDate: Thu Feb 19 18:14:28 2026 +0100 Commit: Michael Niedermayer <[email protected]> CommitDate: Mon May 4 17:13:28 2026 +0200 fftools/ffmpeg_demux: Check metadata provided filename Fixes: path traversal with -dump_attachment:t Fixes: malicious.mkv Based on code from libavformat/concatdec.c This will be factored out possibly into libavutil once there is agreement on the API Found-by: Shangzhi Xu <[email protected]> Signed-off-by: Michael Niedermayer <[email protected]> (cherry picked from commit 1e7d7c4f5203a5badc63de82747b5abb1e56b5a0) Signed-off-by: Michael Niedermayer <[email protected]> --- fftools/ffmpeg_demux.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 1ca40eda5a..9a6e7e15a7 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -1280,6 +1280,56 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) return 0; } +static int is_windows_reserved_device_name(const char *f) +{ +#if HAVE_DOS_PATHS + for (const char *p = f; p && *p; ) { + char stem[6], *s; + av_strlcpy(stem, p, sizeof(stem)); + if ((s = strchr(stem, '.'))) + *s = 0; + if ((s = strpbrk(stem, "123456789"))) + *s = '1'; + + if( !av_strcasecmp(stem, "AUX") || + !av_strcasecmp(stem, "CON") || + !av_strcasecmp(stem, "NUL") || + !av_strcasecmp(stem, "PRN") || + !av_strcasecmp(stem, "COM1") || + !av_strcasecmp(stem, "LPT1") + ) + return 1; + + p = strchr(p, '/'); + if (p) + p++; + } +#endif + return 0; +} + +static int safe_filename(const char *f, int allow_subdir) +{ + const char *start = f; + + if (!*f || is_windows_reserved_device_name(f)) + return 0; + + for (; *f; f++) { + /* A-Za-z0-9_- */ + if (!((unsigned)((*f | 32) - 'a') < 26 || + (unsigned)(*f - '0') < 10 || *f == '_' || *f == '-')) { + if (f == start) + return 0; + else if (allow_subdir && *f == '/') + start = f + 1; + else if (*f != '.') + return 0; + } + } + return 1; +} + static int dump_attachment(InputStream *ist, const char *filename) { AVStream *st = ist->st; @@ -1291,8 +1341,13 @@ static int dump_attachment(InputStream *ist, const char *filename) av_log(ist, AV_LOG_WARNING, "No extradata to dump.\n"); return 0; } - if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0))) + if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0))) { filename = e->value; + if (!safe_filename(filename, 0)) { + av_log(ist, AV_LOG_ERROR, "Filename %s is unsafe\n", filename); + return AVERROR(EINVAL); + } + } if (!*filename) { av_log(ist, AV_LOG_FATAL, "No filename specified and no 'filename' tag"); return AVERROR(EINVAL); _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
