diff --git a/changelogs/unreleased/4478-provide-an-option-to-disable-certain-risky-redis-commands.yml b/changelogs/unreleased/4478-provide-an-option-to-disable-certain-risky-redis-commands.yml
new file mode 100644
index 0000000000000000000000000000000000000000..dd97e1dc92a5aa846cc42e032fd636aff2faf049_Y2hhbmdlbG9ncy91bnJlbGVhc2VkLzQ0NzgtcHJvdmlkZS1hbi1vcHRpb24tdG8tZGlzYWJsZS1jZXJ0YWluLXJpc2t5LXJlZGlzLWNvbW1hbmRzLnltbA==
--- /dev/null
+++ b/changelogs/unreleased/4478-provide-an-option-to-disable-certain-risky-redis-commands.yml
@@ -0,0 +1,5 @@
+---
+title: Rename unused redis commands by default
+merge_request: 3436
+author:
+type: security
diff --git a/doc/settings/redis.md b/doc/settings/redis.md
index 47c3fd31dc42a84f4dd059f486d424af76c696f3_ZG9jL3NldHRpbmdzL3JlZGlzLm1k..dd97e1dc92a5aa846cc42e032fd636aff2faf049_ZG9jL3NldHRpbmdzL3JlZGlzLm1k 100644
--- a/doc/settings/redis.md
+++ b/doc/settings/redis.md
@@ -157,6 +157,28 @@
 Redis connection using [stunnel](https://redislabs.com/blog/stunnel-secure-redis-ssl/).
 AWS ElasticCache also supports Redis over SSL.
 
+## Renamed commands
+
+By default, the `KEYS` command is disabled as a security measure.
+
+If you'd like to obfuscate or disable this command, or other commands, edit the `redis['rename_commands']` setting in `/etc/gitlab/gitlab.rb` to look like:
+```ruby
+redis['rename_commands'] = {
+  'KEYS': '',
+  'OTHER_COMMAND': 'VALUE'
+}
+```
+
+* `OTHER_COMMAND` is the command you want to modify
+* `VALUE` should be one of:
+  1. A new command name.
+  1. '', which completely disables the command
+
+To disable this functionality:
+
+1. Set `redis['rename_commands'] = {}` in your `/etc/gitlab/gitlab.rb` file
+1. Run `sudo gitlab-ctl reconfigure`
+
 ### Limitations
 
 - GitLab does NOT ship with stunnel or other tools to provide encryption
diff --git a/files/gitlab-config-template/gitlab.rb.template b/files/gitlab-config-template/gitlab.rb.template
index 47c3fd31dc42a84f4dd059f486d424af76c696f3_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU=..dd97e1dc92a5aa846cc42e032fd636aff2faf049_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU= 100644
--- a/files/gitlab-config-template/gitlab.rb.template
+++ b/files/gitlab-config-template/gitlab.rb.template
@@ -929,6 +929,16 @@
 # redis['uid'] = nil
 # redis['gid'] = nil
 
+### Disable or obfuscate unnecessary redis command names
+### Uncomment and edit this block to add or remove entries.
+### See https://docs.gitlab.com/omnibus/settings/redis.html#renamed-commands
+### for detailed usage
+###  
+# redis['rename_commands'] = {
+#   'KEYS': ''
+#}
+#
+
 ###! **To enable only Redis service in this machine, uncomment
 ###!   one of the lines below (choose master or slave instance types).**
 ###! Docs: https://docs.gitlab.com/omnibus/settings/redis.html
diff --git a/files/gitlab-cookbooks/gitlab/libraries/redis.rb b/files/gitlab-cookbooks/gitlab/libraries/redis.rb
index 47c3fd31dc42a84f4dd059f486d424af76c696f3_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL3JlZGlzLnJi..dd97e1dc92a5aa846cc42e032fd636aff2faf049_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL3JlZGlzLnJi 100644
--- a/files/gitlab-cookbooks/gitlab/libraries/redis.rb
+++ b/files/gitlab-cookbooks/gitlab/libraries/redis.rb
@@ -46,6 +46,10 @@
         Gitlab['redis']['master_password'] ||= Gitlab['redis']['password']
       end
 
+      Gitlab['redis']['rename_commands'] ||= {
+        'KEYS' => ''
+      }
+
       return unless RedisHelper::Checks.sentinel_daemon_enabled? || RedisHelper::Checks.is_redis_slave?
 
       raise "redis 'master_ip' is not defined" unless Gitlab['redis']['master_ip']
diff --git a/files/gitlab-cookbooks/redis/attributes/attributes.rb b/files/gitlab-cookbooks/redis/attributes/attributes.rb
index 47c3fd31dc42a84f4dd059f486d424af76c696f3_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy9hdHRyaWJ1dGVzL2F0dHJpYnV0ZXMucmI=..dd97e1dc92a5aa846cc42e032fd636aff2faf049_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy9hdHRyaWJ1dGVzL2F0dHJpYnV0ZXMucmI= 100644
--- a/files/gitlab-cookbooks/redis/attributes/attributes.rb
+++ b/files/gitlab-cookbooks/redis/attributes/attributes.rb
@@ -34,6 +34,8 @@
 default['redis']['client_output_buffer_limit_pubsub'] = "32mb 8mb 60"
 default['redis']['save'] = ['900 1', '300 10', '60 10000']
 
+default['redis']['rename_commands'] = nil
+
 ####
 # Redis Settings for EE
 # They are no-op in CE
diff --git a/files/gitlab-cookbooks/redis/templates/default/redis.conf.erb b/files/gitlab-cookbooks/redis/templates/default/redis.conf.erb
index 47c3fd31dc42a84f4dd059f486d424af76c696f3_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy90ZW1wbGF0ZXMvZGVmYXVsdC9yZWRpcy5jb25mLmVyYg==..dd97e1dc92a5aa846cc42e032fd636aff2faf049_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy90ZW1wbGF0ZXMvZGVmYXVsdC9yZWRpcy5jb25mLmVyYg== 100644
--- a/files/gitlab-cookbooks/redis/templates/default/redis.conf.erb
+++ b/files/gitlab-cookbooks/redis/templates/default/redis.conf.erb
@@ -509,7 +509,11 @@
 #
 # Please note that changing the name of commands that are logged into the
 # AOF file or transmitted to slaves may cause problems.
-
+<% if @rename_commands %>
+  <% @rename_commands.each_pair do |command, newname| %>
+rename-command <%= command %> "<%= newname %>"
+  <% end %>
+<% end %>
 ################################### LIMITS ####################################
 
 # Set the max number of connected clients at the same time. By default
diff --git a/spec/chef/redis/redis_spec.rb b/spec/chef/redis/redis_spec.rb
index 47c3fd31dc42a84f4dd059f486d424af76c696f3_c3BlYy9jaGVmL3JlZGlzL3JlZGlzX3NwZWMucmI=..dd97e1dc92a5aa846cc42e032fd636aff2faf049_c3BlYy9jaGVmL3JlZGlzL3JlZGlzX3NwZWMucmI= 100644
--- a/spec/chef/redis/redis_spec.rb
+++ b/spec/chef/redis/redis_spec.rb
@@ -10,29 +10,21 @@
   context 'by default' do
     it 'creates redis config with default values' do
       expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/client-output-buffer-limit normal 0 0 0/)
-      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/client-output-buffer-limit slave 256mb 64mb 60/)
-      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/client-output-buffer-limit pubsub 32mb 8mb 60/)
-      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/^hz 10/)
-      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/^save 900 1/)
-      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/^save 300 10/)
-      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/^save 60 10000/)
-      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/^maxmemory 0/)
-      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/^maxmemory-policy noeviction/)
-      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/^maxmemory-samples 5/)
-      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/^tcp-backlog 511/)
-      expect(chef_run).not_to render_file('/var/opt/gitlab/redis/redis.conf')
-        .with_content(/^slaveof/)
+        .with_content { |content|
+          expect(content).to match(/client-output-buffer-limit normal 0 0 0/)
+          expect(content).to match(/client-output-buffer-limit slave 256mb 64mb 60/)
+          expect(content).to match(/client-output-buffer-limit pubsub 32mb 8mb 60/)
+          expect(content).to match(/^hz 10/)
+          expect(content).to match(/^save 900 1/)
+          expect(content).to match(/^save 300 10/)
+          expect(content).to match(/^save 60 10000/)
+          expect(content).to match(/^maxmemory 0/)
+          expect(content).to match(/^maxmemory-policy noeviction/)
+          expect(content).to match(/^maxmemory-samples 5/)
+          expect(content).to match(/^tcp-backlog 511/)
+          expect(content).to match(/^rename-command KEYS ""$/)
+          expect(content).not_to match(/^slaveof/)
+        }
     end
 
     it 'creates redis user and group' do
@@ -56,7 +48,11 @@
           tcp_backlog: 1024,
           hz: 100,
           username: 'foo',
-          group: 'bar'
+          group: 'bar',
+          rename_commands: {
+            "FAKE_COMMAND" => "RENAMED_FAKE_COMMAND",
+            "DISABLED_FAKE_COMMAND" => ""
+          }
         }
       )
     end
@@ -82,6 +78,15 @@
         .with_content(/^hz 100/)
     end
 
+    it 'does not include the default renamed keys in redis.conf' do
+      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
+        .with_content { |content|
+          expect(content).not_to match(/^rename-command KEYS ""$/)
+          expect(content).to match(/^rename-command FAKE_COMMAND "RENAMED_FAKE_COMMAND"$/)
+          expect(content).to match(/^rename-command DISABLED_FAKE_COMMAND ""$/)
+        }
+    end
+
     it 'creates redis user and group' do
       expect(chef_run).to create_account('user and group for redis').with(username: 'foo', groupname: 'bar')
     end
@@ -169,6 +174,23 @@
     end
   end
 
+  context 'with rename_commands disabled' do
+    before do
+      stub_gitlab_rb(
+        redis: {
+          rename_commands: {}
+        }
+      )
+    end
+
+    it 'should not rename any commands' do
+      expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf')
+        .with_content { |content|
+          expect(content).not_to match(/^rename-command/)
+        }
+    end
+  end
+
   context 'with redis disabled' do
     before do
       stub_gitlab_rb(redis: { enable: false })