fix(runners): skip unregistered runners for remote tasks#3923
fix(runners): skip unregistered runners for remote tasks#3923cursor[bot] wants to merge 1 commit into
Conversation
Unregistered runners can be created with active=true (for pre-provisioning before registration). RemoteJob was selecting them in the fallback pass when they had no heartbeat or webhook, assigning tasks that could never run and hanging until timeout. Also return 400 from POST /api/runners/register when the token matches neither a one-time smrs_ token nor the global registration token, instead of 200 with an empty auth token. Co-authored-by: Denis Gukov <fiftin@outlook.com>
There was a problem hiding this comment.
Security review
Outcome: No medium, high, or critical vulnerabilities found in this PR.
This change is security-positive: it closes two real gaps in the runner registration and remote-task dispatch paths.
Changes reviewed
-
RegisterRunner— reject unrecognized registration tokens (400)
Before this fix, tokens that were neither a validsmrs_one-time token nor the configured global token fell through and returned HTTP 200 with{"token":""}and loggedrunner_id: 0. That is a misleading success response and a minor token-validation oracle (invalidsmrs_→ 400 vs. other invalid tokens → 200). The newelsebranch correctly rejects those requests. -
filterRegisteredRunnersinRemoteJob
Unregistered runners (Token == "") could previously be selected for remote tasks whenactive: true(Terraform pre-provisioning). That allowedcallRunnerWebhookto POST task metadata (project_id,task_id,template_id,runner_id) to a runner webhook even though the runner had no auth token and could not execute work. Filtering onIsRegistered()before selection closes that path. Runner creation still requires admin/project-manage permissions or the global registration secret (pre-existing controls). -
Test updates — documentation-only; no new attack surface.
Prior threads
No unresolved automation review threads were present on this PR.
Recommendation: Merge from a security perspective.
Sent by Cursor Automation: Find vulnerabilities


Bug and impact
Unregistered runners (created for Terraform pre-provisioning with
active: true) could be selected byRemoteJobwhen no registered runner had a recent heartbeat or webhook. Tasks were assigned to runners that have no auth token and cannot pick up work, causing tasks to hang instartinguntilmax_task_duration_sec(or indefinitely when that limit is unset).A secondary issue:
POST /api/runners/registerreturned HTTP 200 with an empty token when the registration token matched neither a one-timesmrs_token nor the global registration token (regression from the prefix-check refactor in 3e9a9c9).Root cause
af0889f2intentionally allows unregistered runners to be created withactive: true, butRemoteJobonly filtered on theactiveDB flag and heartbeat/webhook — not onIsRegistered()(presence of auth token).RegisterRunnerhandler lost its finalelsebranch when registration flow was split bysmrs_prefix.Fix and validation
RemoteJobbefore runner selection (filterRegisteredRunners).RegisterRunner.runner_svc_testto reflect intentionalactivepreservation for unregistered runners.filterRegisteredRunners.