From 11fafb738d07ecdecb60de665d4062f3f9a56639 Mon Sep 17 00:00:00 2001 From: Ilia Ross Date: Sat, 11 Apr 2026 18:25:22 +0200 Subject: [PATCH] Fix to only show safe files in browser https://github.com/webmin/webmin/issues/1907#issuecomment-4226036213 --- updown/fetch.cgi | 65 +++++++++++++++++++----------------------------- updown/lang/en | 4 +-- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/updown/fetch.cgi b/updown/fetch.cgi index 7c37b8a2c..f10ea2d82 100755 --- a/updown/fetch.cgi +++ b/updown/fetch.cgi @@ -62,56 +62,43 @@ if ($ENV{'PATH_INFO'}) { # Work out the type &open_readfile(FILE, $file) || &error(&text('fetch_eopen', $!)); + my $type = "application/octet-stream"; + my $show_inline = 0; if ($fetch_show) { - $type = &guess_mime_type($file, undef); - if (!$type) { - # See if it is really text - $out = &backquote_command("file ". + # Only allow file types that are safe to render inside a + # Webmin session. Everything else must be downloaded. + my $guessed_type = + &guess_mime_type($file, "application/octet-stream"); + if ($guessed_type =~ /^image\/(?:gif|png|jpe?g)$/i) { + $type = $guessed_type; + $show_inline = 1; + } + elsif ($guessed_type =~ /^text\//i && + $guessed_type !~ /^text\/(?:html|xml)$/i) { + $type = "text/plain"; + $show_inline = 1; + } + else { + my $file_desc = &backquote_command("file ". quotemeta(&resolve_links($file))); - $type = "text/plain" if ($out =~ /text|script/); + if ($file_desc =~ /\btext\b/i && + $file_desc !~ /\b(?:html|xml|svg|pdf)\b/i) { + $type = "text/plain"; + $show_inline = 1; + } } } - else { + if (!$show_inline) { print "Content-Disposition: Attachment\n"; } # Send it - $type ||= "application/octet-stream"; - if (!$fetch_show) { - print "Content-Disposition: Attachment\n"; - } - # Stat file my @st = stat($file); - my $fsize = $st[7]; - - # Get and analyze the file contents first - my $fdata = ""; - my $dangertypes = $type =~ /html|xml|pdf/i; - my $htmltype = $type =~ /html/i ? 1 : 0; - my $pdftype = $type =~ /pdf/i ? 'pdf' : 0; - if ($dangertypes) { - $fdata = do { local $/; }; - my $fdata_filtered = &filter_javascript($fdata, $pdftype); - # If content was changed upon - # filtering force download it - if ($fdata_filtered ne $fdata) { - $type = "application/octet-stream"; - print "Content-Disposition: Attachment\n"; - } - } - - print "Content-length: $fsize\n"; + print "Content-length: $st[7]\n"; print "X-Content-Type-Options: nosniff\n"; print "Content-type: $type\n\n"; - # File is already read, so print it - if ($dangertypes) { - print "$fdata"; - } - else { - # Send the file - while(read(FILE, $buffer, &get_buffer_size_binary())) { - print("$buffer"); - } + while(read(FILE, $buffer, &get_buffer_size_binary())) { + print("$buffer"); } close(FILE); } diff --git a/updown/lang/en b/updown/lang/en index 0404108d3..d9487283b 100644 --- a/updown/lang/en +++ b/updown/lang/en @@ -30,13 +30,13 @@ index_zipyes=Yes, then delete index_header3=Download file from server to PC index_fetch=File to download index_ok2=Download -index_show=Show in browser if possible? +index_show=Show safe files in browser? index_tabdownload=Download from web index_tabupload=Upload to server index_tabfetch=Download from server index_descdownload=This form allows you to download files or web pages from HTTP or FTP URLs to the system running Webmin. The download can be done immediately, or scheduled for some time in the future. index_descupload=This page allows you to upload one or more files from the PC on which your web browser runs to the system running Webmin. -index_descfetch=This page is for downloading a file from the system running Webmin for display in your browser or saving on the same system. +index_descfetch=This page is for downloading a file from the system running Webmin for display in your browser when it is a safe text or image type, or saving it to your computer if it is not. index_email=Send email when downloads are done? index_emailto=Yes, to address index_email2=Send email when uploads are done?