FIX: Correctly escape category description text (#8107)

FIX: Correctly escape category description text (#8107)

diff --git a/app/assets/javascripts/discourse/helpers/category-link.js.es6 b/app/assets/javascripts/discourse/helpers/category-link.js.es6
index 3b62c82..7f02dae 100644
--- a/app/assets/javascripts/discourse/helpers/category-link.js.es6
+++ b/app/assets/javascripts/discourse/helpers/category-link.js.es6
@@ -75,7 +75,7 @@ export function categoryLinkHTML(category, options) {
 registerUnbound("category-link", categoryLinkHTML);
 
 function defaultCategoryLinkRenderer(category, opts) {
-  let description = get(category, "description_text");
+  let descriptionText = get(category, "description_text");
   let restricted = get(category, "read_restricted");
   let url = opts.url
     ? opts.url
@@ -121,7 +121,7 @@ function defaultCategoryLinkRenderer(category, opts) {
     'data-drop-close="true" class="' +
     classNames +
     '"' +
-    (description ? 'title="' + escapeExpression(description) + '" ' : "") +
+    (descriptionText ? 'title="' + descriptionText + '" ' : "") +
     ">";
 
   let categoryName = escapeExpression(get(category, "name"));
diff --git a/app/assets/javascripts/select-kit/components/category-row.js.es6 b/app/assets/javascripts/select-kit/components/category-row.js.es6
index c0c3657..2915301 100644
--- a/app/assets/javascripts/select-kit/components/category-row.js.es6
+++ b/app/assets/javascripts/select-kit/components/category-row.js.es6
@@ -84,9 +84,9 @@ export default SelectKitRowComponent.extend({
   },
 
   @computed("category.description_text")
-  descriptionText(description) {
-    if (description) {
-      return this._formatCategoryDescription(description);
+  descriptionText(descriptionText) {
+    if (descriptionText) {
+      return this._formatCategoryDescription(descriptionText);
     }
   },
 
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 9d7b6e4..34f92d7 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -437,17 +437,14 @@ module ApplicationHelper
 
   def theme_lookup(name)
     Theme.lookup_field(theme_ids, mobile_view? ? :mobile : :desktop, name)
-      &.html_safe
   end
 
   def theme_translations_lookup
     Theme.lookup_field(theme_ids, :translations, I18n.locale)
-      &.html_safe
   end
 
   def theme_js_lookup
     Theme.lookup_field(theme_ids, :extra_js, nil)
-      &.html_safe
   end
 
   def discourse_stylesheet_link_tag(name, opts = {})
diff --git a/app/models/category.rb b/app/models/category.rb
index 6009164..af7b073 100644
--- a/app/models/category.rb
+++ b/app/models/category.rb
@@ -261,7 +261,8 @@ class Category < ActiveRecord::Base
 
     @@cache ||= LruRedux::ThreadSafeCache.new(1000)
     @@cache.getset(self.description) do
-      Nokogiri::HTML.fragment(self.description).text.strip.html_safe
+      text = Nokogiri::HTML.fragment(self.description).text.strip
+      Rack::Utils.escape_html(text).html_safe
     end
   end
 
diff --git a/app/views/users/omniauth_callbacks/complete.html.erb b/app/views/users/omniauth_callbacks/complete.html.erb
index 5eb0ab9..dc6a0b0 100644
--- a/app/views/users/omniauth_callbacks/complete.html.erb
+++ b/app/views/users/omniauth_callbacks/complete.html.erb
@@ -26,7 +26,7 @@
   <div class="dialog">
     <p>
       <%=t "login.auth_complete" %>
-      <a href="<%= Discourse.base_url.html_safe %>?authComplete=true"><%= t("login.click_to_continue") %></a>
+      <a href="<%= Discourse.base_url %>?authComplete=true"><%= t("login.click_to_continue") %></a>
     </p>
   </div>
 </body>
diff --git a/spec/components/category_badge_spec.rb b/spec/components/category_badge_spec.rb
index a5636c9..76eb8c2 100644
--- a/spec/components/category_badge_spec.rb
+++ b/spec/components/category_badge_spec.rb
@@ -14,4 +14,11 @@ describe CategoryBadge do
     expect(html).to include(ERB::Util.html_escape("<b>name</b>"))
     expect(html).to include("title='title'")
   end
+
+  it "escapes code block contents" do
+    c = Fabricate(:category, description: '<code>\' &lt;b id="x"&gt;</code>')
+    html = CategoryBadge.html_for(c)
+
+    expect(html).to include("title='&#x27; &lt;b id=&quot;x&quot;&gt;'")
+  end
 end
diff --git a/spec/models/category_spec.rb b/spec/models/category_spec.rb
index c660a6b..6694483 100644
--- a/spec/models/category_spec.rb
+++ b/spec/models/category_spec.rb
@@ -357,7 +357,7 @@ describe Category do
       c = Category.new
       expect(c.description_text).to be_nil
       c.description = "&lt;hello <a>test</a>."
-      expect(c.description_text).to eq("<hello test.")
+      expect(c.description_text).to eq("&lt;hello test.")
     end
   end

GitHub sha: d407bcab