diff --git a/ee/app/controllers/ee/projects_controller.rb b/ee/app/controllers/ee/projects_controller.rb
index 82f7e5438f19b8f1af61f089be6781704d5f5c76..e119f759df9935adea7a3b3c07921bbbfc0fe0bc 100644
--- a/ee/app/controllers/ee/projects_controller.rb
+++ b/ee/app/controllers/ee/projects_controller.rb
@@ -92,7 +92,6 @@ def project_setting_attributes
       attributes = %i[
         prevent_merge_without_jira_issue
         cve_id_request_enabled
-        duo_features_enabled
         product_analytics_data_collector_host
         cube_api_base_url
         cube_api_key
@@ -107,6 +106,10 @@ def project_setting_attributes
         attributes << :spp_repository_pipeline_access
       end
 
+      unless project&.project_setting&.duo_features_enabled_locked?
+        attributes << :duo_features_enabled
+      end
+
       super + attributes
     end
 
diff --git a/ee/spec/controllers/projects_controller_spec.rb b/ee/spec/controllers/projects_controller_spec.rb
index 730f63c05e2aa5f633d376ab2513f9e03cbc2bd2..f81f286de7361e48397405a5bf801e657bff5c11 100644
--- a/ee/spec/controllers/projects_controller_spec.rb
+++ b/ee/spec/controllers/projects_controller_spec.rb
@@ -6,7 +6,7 @@
   let_it_be(:user) { create(:user) }
   let_it_be(:group) { create(:group) }
 
-  let_it_be(:project, reload: true) { create(:project) }
+  let_it_be(:project, reload: true) { create(:project, namespace: group) }
 
   let_it_be(:public_project) { create(:project, :public, :repository, namespace: group) }
 
@@ -391,24 +391,47 @@
       expect(project.project_setting.cve_id_request_enabled).to eq(true)
     end
 
-    it 'updates duo_features_enabled' do
-      project.project_setting.duo_features_enabled = false
-      project.project_setting.save!
+    context 'when enabling duo features' do
+      let(:params) { { project_setting_attributes: { duo_features_enabled: true } } }
 
-      params = {
-        project_setting_attributes: {
-          duo_features_enabled: true
-        }
-      }
-      put :update,
-        params: {
-          namespace_id: project.namespace,
-          id: project,
-          project: params
-        }
-      project.reload
+      let(:request) do
+        put :update, params: { namespace_id: project.namespace, id: project, project: params }
+      end
+
+      it 'updates duo_features_enabled' do
+        project.project_setting.duo_features_enabled = false
+        project.project_setting.save!
 
-      expect(project.project_setting.duo_features_enabled).to eq(true)
+        request
+
+        expect(project.reload.project_setting.duo_features_enabled).to eq(true)
+      end
+
+      context 'when duo features are locked by the ancestor' do
+        before do
+          project.project_setting.duo_features_enabled = false
+          project.project_setting.save!
+
+          project.namespace.namespace_settings.lock_duo_features_enabled = true
+          project.namespace.namespace_settings.duo_features_enabled = false
+          project.namespace.namespace_settings.save!
+        end
+
+        it 'does not update duo feature' do
+          expect { request }.not_to change { project.reload.project_setting.duo_features_enabled }.from(false)
+        end
+
+        context 'with more params passed' do
+          let(:params) do
+            { project_setting_attributes: { duo_features_enabled: true }, description: 'Settings test' }
+          end
+
+          it 'does not update duo feature, but updates other attributes' do
+            expect { request }.not_to change { project.reload.project_setting.duo_features_enabled }.from(false)
+            expect(project.description).to eq('Settings test')
+          end
+        end
+      end
     end
 
     context 'when merge_pipelines_enabled param is specified' do