diff --git a/app/policies/ci/runner_policy.rb b/app/policies/ci/runner_policy.rb
index 6dfe9cc496bf99012d170520b01dc7f596cc807e..8a99f4d1a3e048404d5ff5243b94744e535b71d6 100644
--- a/app/policies/ci/runner_policy.rb
+++ b/app/policies/ci/runner_policy.rb
@@ -31,3 +31,5 @@ class RunnerPolicy < BasePolicy
     rule { ~admin & locked }.prevent :assign_runner
   end
 end
+
+Ci::RunnerPolicy.prepend_mod_with('Ci::RunnerPolicy')
diff --git a/ee/app/policies/ee/ci/runner_policy.rb b/ee/app/policies/ee/ci/runner_policy.rb
new file mode 100644
index 0000000000000000000000000000000000000000..014bf5d04a19b1869a3bc3429af239341211cc5e
--- /dev/null
+++ b/ee/app/policies/ee/ci/runner_policy.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module EE
+  module Ci
+    module RunnerPolicy
+      extend ActiveSupport::Concern
+
+      prepended do
+        condition(:is_group_runner) do
+          @subject.group_type?
+        end
+
+        condition(:is_project_runner) do
+          @subject.project_type?
+        end
+
+        condition(:enable_auditor_group_runner_access) do
+          ::Feature.enabled?(:auditor_group_runner_access)
+        end
+
+        rule { enable_auditor_group_runner_access & auditor & (is_group_runner | is_project_runner) }.policy do
+          enable :read_runner
+        end
+      end
+    end
+  end
+end
diff --git a/ee/app/policies/ee/group_policy.rb b/ee/app/policies/ee/group_policy.rb
index ec9198bf1715ef88ed9dfeb6140acf826f83f7c8..c4fe0471c606207489081b1b3abdaea0769dfea8 100644
--- a/ee/app/policies/ee/group_policy.rb
+++ b/ee/app/policies/ee/group_policy.rb
@@ -165,6 +165,10 @@ module GroupPolicy
         @user.banned_from_namespace?(root_namespace)
       end
 
+      condition(:enable_auditor_group_runner_access) do
+        ::Feature.enabled?(:auditor_group_runner_access)
+      end
+
       rule { ~public_group & ~can?(:owner_access) & user_banned_from_group }.policy do
         prevent :read_group
       end
@@ -207,6 +211,10 @@ module GroupPolicy
         enable :read_wiki
       end
 
+      rule { enable_auditor_group_runner_access & auditor }.policy do
+        enable :read_group_runners
+      end
+
       rule { group_level_compliance_dashboard_enabled & auditor }.policy do
         enable :read_group_compliance_dashboard
       end
diff --git a/ee/config/feature_flags/development/auditor_group_runner_access.yml b/ee/config/feature_flags/development/auditor_group_runner_access.yml
new file mode 100644
index 0000000000000000000000000000000000000000..77db21aad3708f3a1fbcb98fd45093aef9b4a6a4
--- /dev/null
+++ b/ee/config/feature_flags/development/auditor_group_runner_access.yml
@@ -0,0 +1,8 @@
+---
+name: auditor_group_runner_access
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91553
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368089
+milestone: '15.3'
+type: development
+group: group::runner
+default_enabled: false
diff --git a/ee/spec/policies/ee/ci/runner_policy_spec.rb b/ee/spec/policies/ee/ci/runner_policy_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2cd539523dae68eaaa2bb2c515b4760bfc745fcd
--- /dev/null
+++ b/ee/spec/policies/ee/ci/runner_policy_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::RunnerPolicy do
+  describe 'cicd runners' do
+    let_it_be(:group) { create(:group) }
+    let_it_be(:project) { create(:project, group: group) }
+
+    subject(:policy) { described_class.new(user, runner) }
+
+    context 'with auditor access' do
+      let_it_be(:user) { create(:auditor) }
+      let_it_be(:instance_runner) { create(:ci_runner, :instance) }
+      let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group]) }
+      let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project]) }
+
+      context 'when auditor_group_runner_access FF disabled' do
+        before do
+          stub_feature_flags(auditor_group_runner_access: false)
+        end
+
+        context 'with instance runner' do
+          let(:runner) { instance_runner }
+
+          it 'disallows all permissions' do
+            expect_disallowed :read_runner, :assign_runner, :update_runner, :delete_runner
+          end
+        end
+
+        context 'with group runner' do
+          let(:runner) { group_runner }
+
+          it 'disallows all permissions' do
+            expect_disallowed :read_runner, :assign_runner, :update_runner, :delete_runner
+          end
+        end
+
+        context 'with project runner' do
+          let(:runner) { project_runner }
+
+          it 'disallows all permissions' do
+            expect_disallowed :read_runner, :assign_runner, :update_runner, :delete_runner
+          end
+        end
+      end
+
+      context 'when auditor_group_runner_access FF enabled' do
+        before do
+          stub_feature_flags(auditor_group_runner_access: true)
+        end
+
+        context 'with instance runner' do
+          let(:runner) { instance_runner }
+
+          it 'disallows all permissions' do
+            expect_disallowed :read_runner, :assign_runner, :update_runner, :delete_runner
+          end
+        end
+
+        context 'with group runner' do
+          let(:runner) { group_runner }
+
+          it 'allows only read permissions' do
+            expect_allowed :read_runner
+            expect_disallowed :assign_runner, :update_runner, :delete_runner
+          end
+        end
+
+        context 'with project runner' do
+          let(:runner) { project_runner }
+
+          it 'allows only read permissions' do
+            expect_allowed :read_runner
+            expect_disallowed :assign_runner, :update_runner, :delete_runner
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/ee/spec/policies/group_policy_spec.rb b/ee/spec/policies/group_policy_spec.rb
index af1baec9905cb890d1f37b3b69f55e4bb3e55597..996427480d1a225c3984fa1c196019d8704f36c5 100644
--- a/ee/spec/policies/group_policy_spec.rb
+++ b/ee/spec/policies/group_policy_spec.rb
@@ -21,6 +21,7 @@
       read_group
       read_group_security_dashboard
       read_cluster
+      read_group_runners
     ]
   end
 
@@ -1244,7 +1245,7 @@ def stub_group_saml_config(enabled)
         expect_disallowed(*reporter_permissions)
         expect_disallowed(*(developer_permissions - auditor_permissions))
         expect_disallowed(*maintainer_permissions)
-        expect_disallowed(*owner_permissions)
+        expect_disallowed(*(owner_permissions - auditor_permissions))
       end
     end
   end
@@ -2259,4 +2260,30 @@ def expect_private_group_permissions_as_if_non_member
       end
     end
   end
+
+  describe 'group cicd runners' do
+    context 'auditor' do
+      let(:current_user) { auditor }
+
+      context 'with auditor_group_runner_access FF disabled' do
+        before do
+          stub_feature_flags(auditor_group_runner_access: false)
+        end
+
+        it { is_expected.to be_disallowed(:read_group_runners) }
+        it { is_expected.to be_disallowed(:admin_group_runners) }
+        it { is_expected.to be_disallowed(:register_group_runners) }
+      end
+
+      context 'with auditor_group_runner_access FF enabled' do
+        before do
+          stub_feature_flags(auditor_group_runner_access: true)
+        end
+
+        it { is_expected.to be_allowed(:read_group_runners) }
+        it { is_expected.to be_disallowed(:admin_group_runners) }
+        it { is_expected.to be_disallowed(:register_group_runners) }
+      end
+    end
+  end
 end