SECURITY: Safely decompress files. (#8124)

* FEATURE: Adds an extra protection layer when decompressing files.

* Rename exporter/importer to zip importer. Update old locale

* Added a new composite class to decompress a file with multiple strategies

* Set max file size inside a site setting

* Ensure that file is deleted after compression

* Sanitize path and files before compressing/decompressing
This commit is contained in:
Roman Rizzi
2019-10-03 10:19:35 -03:00
committed by GitHub
parent aaf15944f8
commit 10565e4623
20 changed files with 466 additions and 101 deletions

View File

@ -1,9 +1,9 @@
# frozen_string_literal: true
require 'rails_helper'
require 'theme_store/tgz_exporter'
require 'theme_store/zip_exporter'
describe ThemeStore::TgzExporter do
describe ThemeStore::ZipExporter do
let!(:theme) do
Fabricate(:theme, name: "Header Icons").tap do |theme|
theme.set_field(target: :common, name: :body_tag, value: "<b>testtheme1</b>")
@ -51,7 +51,7 @@ describe ThemeStore::TgzExporter do
end
let(:package) do
exporter = ThemeStore::TgzExporter.new(theme)
exporter = ThemeStore::ZipExporter.new(theme)
filename = exporter.package_filename
FileUtils.cp(filename, dir)
exporter.cleanup!
@ -63,7 +63,7 @@ describe ThemeStore::TgzExporter do
file = 'discourse-header-icons.zip'
dest = 'discourse-header-icons'
Dir.chdir(dir) do
ImportExport::ZipUtils.new.unzip_directory(dir, file, allow_non_root_folder: true)
Compression::Zip.new.decompress(dir, file, allow_non_root_folder: true)
`rm #{file}`
folders = Dir.glob("**/*").reject { |f| File.file?(f) }
@ -120,7 +120,7 @@ describe ThemeStore::TgzExporter do
it "doesn't prepend 'discourse' to filename if already there" do
theme.update!(name: "Discourse Header Icons")
exporter = ThemeStore::TgzExporter.new(theme)
exporter = ThemeStore::ZipExporter.new(theme)
filename = exporter.package_filename
exporter.cleanup!
expect(filename).to end_with "/discourse-header-icons.zip"

View File

@ -3,10 +3,9 @@
# frozen_string_literal: true
require 'rails_helper'
require 'theme_store/tgz_importer'
require 'import_export/zip_utils'
require 'theme_store/zip_importer'
describe ThemeStore::TgzImporter do
describe ThemeStore::ZipImporter do
before do
@temp_folder = "#{Pathname.new(Dir.tmpdir).realpath}/discourse_theme_#{SecureRandom.hex}"
@ -24,11 +23,12 @@ describe ThemeStore::TgzImporter do
it "can import a simple zipped theme" do
Dir.chdir(@temp_folder) do
ImportExport::ZipUtils.new.zip_directory(@temp_folder, 'test')
Compression::Zip.new.compress(@temp_folder, 'test')
FileUtils.rm_rf('test/')
end
importer = ThemeStore::TgzImporter.new("#{@temp_folder}/test.zip")
file_name = 'test.zip'
importer = ThemeStore::ZipImporter.new("#{@temp_folder}/#{file_name}", file_name)
importer.import!
expect(importer["hello.txt"]).to eq("hello world")
@ -42,7 +42,8 @@ describe ThemeStore::TgzImporter do
`tar -cvzf test.tar.gz test/* 2> /dev/null`
end
importer = ThemeStore::TgzImporter.new("#{@temp_folder}/test.tar.gz")
file_name = 'test.tar.gz'
importer = ThemeStore::ZipImporter.new("#{@temp_folder}/#{file_name}", file_name)
importer.import!
expect(importer["hello.txt"]).to eq("hello world")