diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb
index dc825557928a4bdd9473b5ba376126bbae79e0f9..8267b14941dff11bf55e96e456b30710cbf05545 100644
--- a/app/controllers/projects/runner_projects_controller.rb
+++ b/app/controllers/projects/runner_projects_controller.rb
@@ -6,8 +6,7 @@ class Projects::RunnerProjectsController < Projects::ApplicationController
   def create
     @runner = Ci::Runner.find(params[:runner_project][:runner_id])
 
-    return head(409) if @runner.is_shared? || @runner.locked?
-    return head(409) unless current_user.ci_authorized_runners.include?(@runner)
+    return head(403) unless can?(current_user, :assign_runner, @runner)
 
     path = runners_path(project)
     runner_project = @runner.assign_to(project, current_user)
diff --git a/app/models/ability.rb b/app/models/ability.rb
index f5950879ccb5ce3637c12d228d61bbbab2b11190..0add2f5a34a6736658a7d16b7edb4d3ecd9b46f6 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -19,6 +19,7 @@ class Ability
       when ProjectMember then project_member_abilities(user, subject)
       when User then user_abilities
       when ExternalIssue, Deployment, Environment then project_abilities(user, subject.project)
+      when Ci::Runner then runner_abilities(user, subject)
       else []
       end.concat(global_abilities(user))
     end
@@ -512,6 +513,18 @@ class Ability
       rules
     end
 
+    def runner_abilities(user, runner)
+      if user.is_admin?
+        [:assign_runner]
+      elsif runner.is_shared? || runner.locked?
+        []
+      elsif user.ci_authorized_runners.include?(runner)
+        [:assign_runner]
+      else
+        []
+      end
+    end
+
     def user_abilities
       [:read_user]
     end