diff --git a/app/validators/abstract_path_validator.rb b/app/validators/abstract_path_validator.rb
index e43b66cbe3a09e2c569d592ced8db1d27634d6ae..45ac695c5ec5fc0f578f9f536d6bd9f411790105 100644
--- a/app/validators/abstract_path_validator.rb
+++ b/app/validators/abstract_path_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 class AbstractPathValidator < ActiveModel::EachValidator
   extend Gitlab::EncodingHelper
 
diff --git a/app/validators/certificate_fingerprint_validator.rb b/app/validators/certificate_fingerprint_validator.rb
index 17df756183a994b413aa3bfbfa20ba367f95370e..79d78653ec70b15091093c2550d775aa4108f4af 100644
--- a/app/validators/certificate_fingerprint_validator.rb
+++ b/app/validators/certificate_fingerprint_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 class CertificateFingerprintValidator < ActiveModel::EachValidator
   FINGERPRINT_PATTERN = /\A([a-zA-Z0-9]{2}[\s\-:]?){16,}\z/.freeze
 
diff --git a/app/validators/certificate_key_validator.rb b/app/validators/certificate_key_validator.rb
index 8c7bb75033914af53fdb4decfc6eea0350a5e9f4..5b2bbffc066202572f9cabc080b9a93320506bbd 100644
--- a/app/validators/certificate_key_validator.rb
+++ b/app/validators/certificate_key_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # UrlValidator
 #
 # Custom validator for private keys.
diff --git a/app/validators/certificate_validator.rb b/app/validators/certificate_validator.rb
index b0c9a1b92a4b0a84a12ba6c748ec37604b86e6f5..de8bb179dfb0494a104a6f9d706a83c8a69eef5c 100644
--- a/app/validators/certificate_validator.rb
+++ b/app/validators/certificate_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # UrlValidator
 #
 # Custom validator for private keys.
diff --git a/app/validators/cluster_name_validator.rb b/app/validators/cluster_name_validator.rb
index e7d325501767f5785eae8bee9ebad4e110ea91a8..85fd63f08e517825eefbff26afddc1aaaf2277b1 100644
--- a/app/validators/cluster_name_validator.rb
+++ b/app/validators/cluster_name_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # ClusterNameValidator
 #
 # Custom validator for ClusterName.
diff --git a/app/validators/color_validator.rb b/app/validators/color_validator.rb
index 571d0007aa2d111bf6bd4416584e5493f19d78f5..1932d042e830fa2c6b01914aa719f60adef3516a 100644
--- a/app/validators/color_validator.rb
+++ b/app/validators/color_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # ColorValidator
 #
 # Custom validator for web color codes. It requires the leading hash symbol and
diff --git a/app/validators/cron_timezone_validator.rb b/app/validators/cron_timezone_validator.rb
index 542c7d006ad22d333b614d640b0c1ec76393ea18..c5f51d6506071650aaad06b18550a668e496191f 100644
--- a/app/validators/cron_timezone_validator.rb
+++ b/app/validators/cron_timezone_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # CronTimezoneValidator
 #
 # Custom validator for CronTimezone.
diff --git a/app/validators/cron_validator.rb b/app/validators/cron_validator.rb
index 981fade47a6a31beb942dbe2df0f3c469ba84df5..bd48a7a6efbefb365d659a3b670d78abb16019dc 100644
--- a/app/validators/cron_validator.rb
+++ b/app/validators/cron_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # CronValidator
 #
 # Custom validator for Cron.
diff --git a/app/validators/duration_validator.rb b/app/validators/duration_validator.rb
index 10ff44031c6616101a1e0ae7ad85e368ef606360..811828169ca388f25577edd25745fecdef7f1c2e 100644
--- a/app/validators/duration_validator.rb
+++ b/app/validators/duration_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # DurationValidator
 #
 # Validate the format conforms with ChronicDuration
diff --git a/app/validators/email_validator.rb b/app/validators/email_validator.rb
index aab07a7ece4531264c6460147d1fc3d05bd20383..9459edb7515f3a6332ac29685764d4e8f20d961f 100644
--- a/app/validators/email_validator.rb
+++ b/app/validators/email_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 class EmailValidator < ActiveModel::EachValidator
   def validate_each(record, attribute, value)
     record.errors.add(attribute, :invalid) unless value =~ Devise.email_regexp
diff --git a/app/validators/key_restriction_validator.rb b/app/validators/key_restriction_validator.rb
index 204be827941c6a309d35825c0a524e4625e587ae..891d13b15964cd12ffd01a8382eb0fbda1cb55b4 100644
--- a/app/validators/key_restriction_validator.rb
+++ b/app/validators/key_restriction_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 class KeyRestrictionValidator < ActiveModel::EachValidator
   FORBIDDEN = -1
 
diff --git a/app/validators/line_code_validator.rb b/app/validators/line_code_validator.rb
index ed29e5aeb67f08f3e401db4c0f5f815ecf4766b9..a351180790ed5fce10d4df955409537873761476 100644
--- a/app/validators/line_code_validator.rb
+++ b/app/validators/line_code_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # LineCodeValidator
 #
 # Custom validator for GitLab line codes.
diff --git a/app/validators/namespace_name_validator.rb b/app/validators/namespace_name_validator.rb
index 2e51af2982d59035420e458e50e073f27153e645..fb1c241037ceeb203edffae120c3591d7e4bea72 100644
--- a/app/validators/namespace_name_validator.rb
+++ b/app/validators/namespace_name_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # NamespaceNameValidator
 #
 # Custom validator for GitLab namespace name strings.
diff --git a/app/validators/namespace_path_validator.rb b/app/validators/namespace_path_validator.rb
index 7b0ae4db5d43d1e72fbb3dbcd5d1710d15ae7a94..c078b272b2f1565ebde5b528c95e96cb65c2e059 100644
--- a/app/validators/namespace_path_validator.rb
+++ b/app/validators/namespace_path_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 class NamespacePathValidator < AbstractPathValidator
   extend Gitlab::EncodingHelper
 
diff --git a/app/validators/project_path_validator.rb b/app/validators/project_path_validator.rb
index 424fd77a6a3b07807b2cb1f263bb63d9dc7de97d..aea0a68e7cf9099517a9c6c39408a4dd142a00f8 100644
--- a/app/validators/project_path_validator.rb
+++ b/app/validators/project_path_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 class ProjectPathValidator < AbstractPathValidator
   extend Gitlab::EncodingHelper
 
diff --git a/app/validators/public_url_validator.rb b/app/validators/public_url_validator.rb
index 1e8118fccbb6a6ecaaefa0949817ec986882e684..3ff880deedd011d9a785a99e770e130c49e0a499 100644
--- a/app/validators/public_url_validator.rb
+++ b/app/validators/public_url_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # PublicUrlValidator
 #
 # Custom validator for URLs. This validator works like UrlValidator but
diff --git a/app/validators/top_level_group_validator.rb b/app/validators/top_level_group_validator.rb
index 7e2e735e0cf605dc5e94b2ddb8472cb40ee3e4c7..b50c9dca154f2ac9b6dc3e7f3c5229f4e370ea5f 100644
--- a/app/validators/top_level_group_validator.rb
+++ b/app/validators/top_level_group_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 class TopLevelGroupValidator < ActiveModel::EachValidator
   def validate_each(record, attribute, value)
     if value&.subgroup?
diff --git a/app/validators/url_validator.rb b/app/validators/url_validator.rb
index 6854fec582ed3ba654d1d1672ca5ed6174f1e1ad..faaf1283078fcdb1ee43371dd5f8ad64fad7f76a 100644
--- a/app/validators/url_validator.rb
+++ b/app/validators/url_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # UrlValidator
 #
 # Custom validator for URLs.
diff --git a/app/validators/variable_duplicates_validator.rb b/app/validators/variable_duplicates_validator.rb
index 72660be6c43fd458b26211089465c06981179e2d..90193e85f2a863428edddad8d076451bbdf9a734 100644
--- a/app/validators/variable_duplicates_validator.rb
+++ b/app/validators/variable_duplicates_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # VariableDuplicatesValidator
 #
 # This validator is designed for especially the following condition
@@ -22,8 +24,8 @@ def validate_each(record, attribute, value)
   def validate_duplicates(record, attribute, values)
     duplicates = values.reject(&:marked_for_destruction?).group_by(&:key).select { |_, v| v.many? }.map(&:first)
     if duplicates.any?
-      error_message = "have duplicate values (#{duplicates.join(", ")})"
-      error_message += " for #{values.first.send(options[:scope])} scope" if options[:scope] # rubocop:disable GitlabSecurity/PublicSend
+      error_message = +"have duplicate values (#{duplicates.join(", ")})"
+      error_message << " for #{values.first.send(options[:scope])} scope" if options[:scope] # rubocop:disable GitlabSecurity/PublicSend
       record.errors.add(attribute, error_message)
     end
   end
diff --git a/changelogs/unreleased/frozen-string-enable-app-validators.yml b/changelogs/unreleased/frozen-string-enable-app-validators.yml
new file mode 100644
index 0000000000000000000000000000000000000000..db480b06d9b0f23a2a52239189acf34d010c0f08
--- /dev/null
+++ b/changelogs/unreleased/frozen-string-enable-app-validators.yml
@@ -0,0 +1,5 @@
+---
+title: Enable frozen string in apps/validators/*.rb
+merge_request: 20220
+author: gfyoung
+type: other