Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-08-31 18:10:29 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-31 18:10:29 +0300
commitd7918f34666a538be467cb9db04630960e3659d3 (patch)
treea1e937ec7569d081a4382ca8d2ca9f6968e0a38f /app/models/concerns/sanitizable.rb
parenta9ae162270049d3a183024e0b1f1626dbe14e847 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/models/concerns/sanitizable.rb')
-rw-r--r--app/models/concerns/sanitizable.rb52
1 files changed, 52 insertions, 0 deletions
diff --git a/app/models/concerns/sanitizable.rb b/app/models/concerns/sanitizable.rb
new file mode 100644
index 00000000000..05756beb404
--- /dev/null
+++ b/app/models/concerns/sanitizable.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+# == Sanitizable concern
+#
+# This concern adds HTML sanitization and validation to models. The intention is
+# to help prevent XSS attacks in the event of a by-pass in the frontend
+# sanitizer due to a configuration issue or a vulnerability in the sanitizer.
+# This approach is commonly referred to as defense-in-depth.
+#
+# Example:
+#
+# module Dast
+# class Profile < ApplicationRecord
+# include Sanitizable
+#
+# sanitizes! :name, :description
+
+module Sanitizable
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def sanitize(input)
+ return unless input
+
+ # We return the input unchanged to avoid escaping pre-escaped HTML fragments.
+ # Please see gitlab-org/gitlab#293634 for an example.
+ return input unless input == CGI.unescapeHTML(input.to_s)
+
+ CGI.unescapeHTML(Sanitize.fragment(input))
+ end
+
+ def sanitizes!(*attrs)
+ instance_eval do
+ before_validation do
+ attrs.each do |attr|
+ input = public_send(attr) # rubocop: disable GitlabSecurity/PublicSend
+
+ public_send("#{attr}=", self.class.sanitize(input)) # rubocop: disable GitlabSecurity/PublicSend
+ end
+ end
+
+ validates_each(*attrs) do |record, attr, input|
+ # We reject pre-escaped HTML fragments as invalid to avoid saving them
+ # to the database.
+ unless input.to_s == CGI.unescapeHTML(input.to_s)
+ record.errors.add(attr, 'cannot contain escaped HTML entities')
+ end
+ end
+ end
+ end
+ end
+end