fix(commands): require trusted session for /mcp and /plugins#6002
Merged
Conversation
bug-ops
enabled auto-merge (squash)
July 11, 2026 00:04
McpCommand and PluginsCommand left requires_auth() at its default false, so untrusted remote channels (Telegram/Discord/Slack/gateway) could invoke /mcp add to spawn an arbitrary local subprocess with the default allowed_commands allowlist, or /plugins add to install a plugin from an arbitrary local path, with no authentication. Both handlers now override requires_auth() to return true, matching the same defect class already fixed for /image.
bug-ops
force-pushed
the
fix/5997-mcp-plugins-auth-bypass
branch
from
July 11, 2026 00:18
b02fbeb to
528bc49
Compare
This was referenced Jul 11, 2026
Closed
bug-ops
added a commit
that referenced
this pull request
Jul 13, 2026
… durable replay dedup (#6203) CommandHandler::requires_auth() defaulted to false (accessible from all channels), a recurring defect class where new handlers silently stayed reachable from untrusted remote channels until an audit caught them (4th recurrence: #5967/#5988, #5997/#6002, #6003/PR#6033). Flip the default to true (fail-closed); the six previously-implicit read-only handlers now override it explicitly to preserve behavior. Also fixes durable subagent replay's channel-notify side effects, which bypassed the ctx.step() dedup discipline (spec-064 INV-10): a resumed parent could refire the "replayed from durable journal" notice on every restart. Rather than gating via ctx.step (found to break step-id determinism between fresh and replay runs), dedup via an out-of-band notified_at claim column on durable_promises, consuming no step id. Tightens the doc comment on resolve_durable_spawn_gate's still-pending resume branch to make the LocalBackend-only safety rationale explicit at the call site. Closes #6034 Closes #6027 Closes #6010
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
McpCommandandPluginsCommandnever overrodeCommandHandler::requires_auth(), defaulting tofalse, so untrusted remote channels (Telegram/Discord/Slack/gateway) could dispatch/mcp addand/plugins addwithout authentication/mcp add <id> <command> [args...]spawns a local subprocess; with the shipped defaultmcp.allowed_commandsallowlist (npx,uvx,node,python,python3), this is unauthenticated remote code execution/plugins add <path>installs a plugin from an arbitrary local path with no path-guard checkrequires_auth()to returntrue, matching the same defect class already fixed for/image(SECURITY: /image command allows unauthenticated remote users (Telegram/Discord/Slack) to read arbitrary files under the server's working directory #5967 / fix(commands): require trusted session for /image path reads #5988)CommandRegistry, asserting rejection when untrusted and success when trusted, mirroring the existing/imagetest patternCloses #5997
Test plan
cargo +nightly fmt --checkcargo clippy --profile ci --workspace --all-targets --features "desktop,ide,server,chat,pdf,scheduler,testing" -- -D warningscargo nextest run --config-file .github/nextest.toml -p zeph-commands(137 passed)RUSTDOCFLAGS="--deny rustdoc::broken_intra_doc_links" cargo doc --no-deps --all-features -p zeph-commandsCommandRegistry::dispatchgate, not just the trait method