Skip to content

fix: require executor key for runtime command execution - #257

Merged
abnegate merged 4 commits into
mainfrom
cursor/secure-runtime-commands-9e22
Oct 5, 2026
Merged

abnegate merged 4 commits into
mainfrom
cursor/secure-runtime-commands-9e22

Conversation

@abnegate

@abnegate abnegate commented Oct 4, 2026

Copy link
Copy Markdown
Member

Summary

POST /v1/runtimes/:runtimeId/commands was registered without an HTTP group, so the OPR_EXECUTOR_SECRET init hook — which is scoped to the api group — never ran. Every other sensitive executor route already declares groups(['api', ...]). The commands route therefore accepted unauthenticated requests and could execute commands inside any runtime container.

This is a security fix for Help Scout report HS 1468629 (reporter Kikoichi).

Change

  • Attach groups(['api', 'runtimes']) to POST /v1/runtimes/:runtimeId/commands, matching sibling per-runtime routes (/logs, /executions, get/delete runtime).
  • The existing init hook now rejects requests without a valid executor secret with 401 Missing executor key.
  • /v1/health stays ungrouped so Docker healthchecks remain unauthenticated.

A fail-closed rewrite of the init hook (auth unless a route opts out) was considered. Health was intentionally removed from the api group so compose healthchecks work without a secret; making init global would have to special-case that route and risk changing unrelated 404/health behavior. The missing group was the sole bypass. A unit test now fails if any non-health route is declared without api, so this class of omission cannot land again.

Tests

  • testCommandsUnauthorized — empty executor key on /commands returns 401 with Missing executor key, same contract as testGetRuntimesUnauthorized.
  • RouteAuthTest — every declared HTTP route except /v1/health includes the api group.

Do not include reproduction payloads beyond the 401 assertion. After merge, rotate OPR_EXECUTOR_SECRET on any deployment that exposed the executor on a shared runtimes network.

Open in Web Open in Cursor 

cursoragent and others added 3 commits October 4, 2026 20:17
POST /v1/runtimes/:runtimeId/commands was registered without the api
group, so the OPR_EXECUTOR_SECRET init hook never ran and the route
accepted unauthenticated docker-exec into any runtime.

Co-authored-by: Jake Barnby <abnegate@users.noreply.github.com>
Co-authored-by: Jake Barnby <abnegate@users.noreply.github.com>
Co-authored-by: Jake Barnby <abnegate@users.noreply.github.com>
@abnegate
abnegate marked this pull request as ready for review October 5, 2026 04:20
@abnegate
abnegate requested a balanced review from Copilot October 5, 2026 04:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The route-auth test silently skips a route declared at end-of-file, weakening the security regression guard.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Secures runtime command execution with executor-key authentication.

Changes:

  • Adds api and runtimes groups to the commands route.
  • Tests unauthorized command requests.
  • Adds a route-authentication regression test.
File Description
app/​controllers.php Protects command execution.
tests/​e2e/​ExecutorTest.php Verifies unauthorized requests return 401.
tests/​unit/​Http/​RouteAuthTest.php Checks route group declarations.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/unit/Http/RouteAuthTest.php Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@abnegate
abnegate merged commit 5fe320f into main Oct 5, 2026
6 checks passed
@abnegate
abnegate deleted the cursor/secure-runtime-commands-9e22 branch October 5, 2026 04:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants