SECURITY: Improve theme git import (#12694)

SECURITY: Improve theme git import (#12694)

diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index c20e0e8..bdb8385 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -74,6 +74,7 @@ en:
       about_json_values: "about.json contains invalid values: %{errors}"
       modifier_values: "about.json modifiers contain invalid values: %{errors}"
       git: "Error cloning git repository, access is denied or repository is not found"
+      git_ref_not_found: "Unable to checkout git reference: %{ref}"
       unpack_failed: "Failed to unpack file"
       file_too_big: "The uncompressed file is too big."
       unknown_file_type: "The file you uploaded does not appear to be a valid Discourse theme."
diff --git a/lib/theme_store/git_importer.rb b/lib/theme_store/git_importer.rb
index 553016b..c3f28f5 100644
--- a/lib/theme_store/git_importer.rb
+++ b/lib/theme_store/git_importer.rb
@@ -25,7 +25,16 @@ class ThemeStore::GitImporter
     end
     if version = Discourse.find_compatible_git_resource(@temp_folder)
       Discourse::Utils.execute_command(chdir: @temp_folder) do |runner|
-        return runner.exec("git cat-file -e #{version} || git fetch --depth 1 $(git rev-parse --symbolic-full-name @{upstream} | awk -F '/' '{print $3}') #{version}; git reset --hard #{version}")
+        begin
+          runner.exec "git", "cat-file", "-e", version
+        rescue RuntimeError => e
+          tracking_ref = runner.exec "git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"
+          remote_name = tracking_ref.split("/", 2)[0]
+          runner.exec "git", "fetch", "--depth", "1", remote_name, "#{version}:#{version}"
+        end
+        runner.exec "git", "reset", "--hard", version
+      rescue RuntimeError
+        raise RemoteTheme::ImportError.new(I18n.t("themes.import_error.git_ref_not_found", ref: version))
       end
     end
   end
diff --git a/lib/version.rb b/lib/version.rb
index 334557f..59a67a1 100644
--- a/lib/version.rb
+++ b/lib/version.rb
@@ -54,6 +54,14 @@ module Discourse
       checkout_version = target
     end
 
+    return if checkout_version.nil?
+
+    begin
+      Discourse::Utils.execute_command "git", "check-ref-format", "--allow-onelevel", checkout_version
+    rescue RuntimeError
+      raise InvalidVersionListError, "Invalid ref name: #{checkout_version}"
+    end
+
     checkout_version
   end
 

GitHub sha: 94301854

This commit appears in #12694 which was approved by eviltrout. It was merged by davidtaylorhq.