diff --git a/app/finders/concerns/packages/finder_helper.rb b/app/finders/concerns/packages/finder_helper.rb
index 244bd7f6f86fd49212736e7937414fc533af142c..39c018818d1237c58e7411f945fc70d3c088121f 100644
--- a/app/finders/concerns/packages/finder_helper.rb
+++ b/app/finders/concerns/packages/finder_helper.rb
@@ -13,7 +13,7 @@ def packages_visible_to_user(user, within_group:)
       return ::Packages::Package.none unless within_group
       return ::Packages::Package.none unless Ability.allowed?(user, :read_group, within_group)
 
-      projects = projects_visible_to_reporters(user, within_group.self_and_descendants.select(:id))
+      projects = projects_visible_to_reporters(user, within_group: within_group)
       ::Packages::Package.for_projects(projects.select(:id))
     end
 
@@ -21,12 +21,16 @@ def projects_visible_to_user(user, within_group:)
       return ::Project.none unless within_group
       return ::Project.none unless Ability.allowed?(user, :read_group, within_group)
 
-      projects_visible_to_reporters(user, within_group.self_and_descendants.select(:id))
+      projects_visible_to_reporters(user, within_group: within_group)
     end
 
-    def projects_visible_to_reporters(user, namespace_ids)
-      ::Project.in_namespace(namespace_ids)
-               .public_or_visible_to_user(user, ::Gitlab::Access::REPORTER)
+    def projects_visible_to_reporters(user, within_group:)
+      if user.is_a?(DeployToken) && Feature.enabled?(:packages_finder_helper_deploy_token)
+        user.accessible_projects
+      else
+        within_group.all_projects
+                    .public_or_visible_to_user(user, ::Gitlab::Access::REPORTER)
+      end
     end
 
     def package_type
diff --git a/config/feature_flags/development/packages_finder_helper_deploy_token.yml b/config/feature_flags/development/packages_finder_helper_deploy_token.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fcc73cafd647dc7521e9b8454ccf9a2b7771932b
--- /dev/null
+++ b/config/feature_flags/development/packages_finder_helper_deploy_token.yml
@@ -0,0 +1,8 @@
+---
+name: packages_finder_helper_deploy_token
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58497
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326808
+milestone: '13.11'
+type: development
+group: group::package
+default_enabled: false
diff --git a/spec/finders/concerns/packages/finder_helper_spec.rb b/spec/finders/concerns/packages/finder_helper_spec.rb
index 73f7764757312d6316bc004c3107458bececb679..c1740ee17964da5199c4040ade99ccd367cd6ca9 100644
--- a/spec/finders/concerns/packages/finder_helper_spec.rb
+++ b/spec/finders/concerns/packages/finder_helper_spec.rb
@@ -6,7 +6,6 @@
   describe '#packages_visible_to_user' do
     using RSpec::Parameterized::TableSyntax
 
-    let_it_be(:user) { create(:user) }
     let_it_be_with_reload(:group) { create(:group) }
     let_it_be_with_reload(:project1) { create(:project, namespace: group) }
     let_it_be(:package1) { create(:package, project: project1) }
@@ -44,41 +43,87 @@ def execute(group)
       it { is_expected.to be_empty }
     end
 
-    where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do
-      'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :maintainer | 'returning both packages'
-      'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :developer  | 'returning both packages'
-      'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :guest      | 'returning both packages'
-      'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :anonymous  | 'returning both packages'
-      'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :maintainer | 'returning both packages'
-      'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :developer  | 'returning both packages'
-      'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :guest      | 'returning package1'
-      'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :anonymous  | 'returning package1'
-      'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
-      'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :developer  | 'returning both packages'
-      'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :guest      | 'returning package1'
-      'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :anonymous  | 'returning package1'
-      'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
-      'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer  | 'returning both packages'
-      'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest      | 'returning no packages'
-      'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous  | 'returning no packages'
+    context 'with a user' do
+      let_it_be(:user) { create(:user) }
+
+      where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do
+        'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :maintainer | 'returning both packages'
+        'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :developer  | 'returning both packages'
+        'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :guest      | 'returning both packages'
+        'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :anonymous  | 'returning both packages'
+        'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :maintainer | 'returning both packages'
+        'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :developer  | 'returning both packages'
+        'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :guest      | 'returning package1'
+        'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :anonymous  | 'returning package1'
+        'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
+        'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :developer  | 'returning both packages'
+        'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :guest      | 'returning package1'
+        'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :anonymous  | 'returning package1'
+        'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
+        'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer  | 'returning both packages'
+        'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest      | 'returning no packages'
+        'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous  | 'returning no packages'
+      end
+
+      with_them do
+        before do
+          unless user_role == :anonymous
+            group.send("add_#{user_role}", user)
+            subgroup.send("add_#{user_role}", user)
+            project1.send("add_#{user_role}", user)
+            project2.send("add_#{user_role}", user)
+          end
+
+          project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+          subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+          project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+          group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+        end
+
+        it_behaves_like params[:shared_example_name]
+      end
     end
 
-    with_them do
-      before do
-        unless user_role == :anonymous
-          group.send("add_#{user_role}", user)
-          subgroup.send("add_#{user_role}", user)
-          project1.send("add_#{user_role}", user)
-          project2.send("add_#{user_role}", user)
+    context 'with a group deploy token' do
+      let_it_be(:user) { create(:deploy_token, :group, read_package_registry: true) }
+      let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: user, group: group) }
+
+      shared_examples 'handling all conditions' do
+        where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do
+          'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | 'returning both packages'
+          'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | 'returning both packages'
+          'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | 'returning both packages'
+          'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning both packages'
+        end
+
+        with_them do
+          before do
+            project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+            subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+            project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+            group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+          end
+
+          it_behaves_like params[:shared_example_name]
+        end
+      end
+
+      context 'with packages_finder_helper_deploy_token enabled' do
+        before do
+          expect(group).not_to receive(:all_projects)
         end
 
-        project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
-        subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
-        project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
-        group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+        it_behaves_like 'handling all conditions'
       end
 
-      it_behaves_like params[:shared_example_name]
+      context 'with packages_finder_helper_deploy_token disabled' do
+        before do
+          stub_feature_flags(packages_finder_helper_deploy_token: false)
+          expect(group).to receive(:all_projects).and_call_original
+        end
+
+        it_behaves_like 'handling all conditions'
+      end
     end
   end
 
@@ -121,41 +166,87 @@ def execute(group)
       it { is_expected.to be_empty }
     end
 
-    where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do
-      'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :maintainer | 'returning both projects'
-      'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :developer  | 'returning both projects'
-      'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :guest      | 'returning both projects'
-      'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :anonymous  | 'returning both projects'
-      'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :maintainer | 'returning both projects'
-      'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :developer  | 'returning both projects'
-      'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :guest      | 'returning project1'
-      'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :anonymous  | 'returning project1'
-      'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
-      'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :developer  | 'returning both projects'
-      'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :guest      | 'returning project1'
-      'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :anonymous  | 'returning project1'
-      'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
-      'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer  | 'returning both projects'
-      'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest      | 'returning no project'
-      'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous  | 'returning no project'
+    context 'with a user' do
+      let_it_be(:user) { create(:user) }
+
+      where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do
+        'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :maintainer | 'returning both projects'
+        'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :developer  | 'returning both projects'
+        'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :guest      | 'returning both projects'
+        'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | :anonymous  | 'returning both projects'
+        'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :maintainer | 'returning both projects'
+        'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :developer  | 'returning both projects'
+        'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :guest      | 'returning project1'
+        'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | :anonymous  | 'returning project1'
+        'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
+        'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :developer  | 'returning both projects'
+        'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :guest      | 'returning project1'
+        'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | :anonymous  | 'returning project1'
+        'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
+        'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer  | 'returning both projects'
+        'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest      | 'returning no project'
+        'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous  | 'returning no project'
+      end
+
+      with_them do
+        before do
+          unless user_role == :anonymous
+            group.send("add_#{user_role}", user)
+            subgroup.send("add_#{user_role}", user)
+            project1.send("add_#{user_role}", user)
+            project2.send("add_#{user_role}", user)
+          end
+
+          project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+          subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+          project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+          group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+        end
+
+        it_behaves_like params[:shared_example_name]
+      end
     end
 
-    with_them do
-      before do
-        unless user_role == :anonymous
-          group.send("add_#{user_role}", user)
-          subgroup.send("add_#{user_role}", user)
-          project1.send("add_#{user_role}", user)
-          project2.send("add_#{user_role}", user)
+    context 'with a group deploy token' do
+      let_it_be(:user) { create(:deploy_token, :group, read_package_registry: true) }
+      let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: user, group: group) }
+
+      shared_examples 'handling all conditions' do
+        where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do
+          'PUBLIC'  | 'PUBLIC'  | 'PUBLIC'  | 'returning both projects'
+          'PUBLIC'  | 'PUBLIC'  | 'PRIVATE' | 'returning both projects'
+          'PUBLIC'  | 'PRIVATE' | 'PRIVATE' | 'returning both projects'
+          'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning both projects'
         end
 
-        project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
-        subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
-        project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
-        group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+        with_them do
+          before do
+            project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+            subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+            project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+            group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+          end
+
+          it_behaves_like params[:shared_example_name]
+        end
       end
 
-      it_behaves_like params[:shared_example_name]
+      context 'with packages_finder_helper_deploy_token enabled' do
+        before do
+          expect(group).not_to receive(:all_projects)
+        end
+
+        it_behaves_like 'handling all conditions'
+      end
+
+      context 'with packages_finder_helper_deploy_token disabled' do
+        before do
+          stub_feature_flags(packages_finder_helper_deploy_token: false)
+          expect(group).to receive(:all_projects).and_call_original
+        end
+
+        it_behaves_like 'handling all conditions'
+      end
     end
   end
 end