Skip to content

fix(mcp): reject run_task task names that start with a dash - #13961

Merged
jdx merged 1 commit into
mainfrom
claude/mise-secrets-m0
Oct 5, 2026
Merged

jdx merged 1 commit into
mainfrom
claude/mise-secrets-m0

Conversation

@jdx

@jdx jdx commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

https://entire.io/gh/jdx/mise/trails/427

Requested by Jeff

The MCP run_task tool passed the caller's task straight to mise run, so a task name beginning with - was parsed as a flag. MCP callers are AI agents; the tool should only ever run the task it names.

Before: run_task with task: "--raw" ran mise run --raw (the default task with raw I/O); task: "--cd=/path" ran default in another directory.

After: the call fails with an INVALID_PARAMS error:

invalid task name '--raw': task names cannot start with '-'

An empty name is rejected too (invalid task name '': a task name is required). Normal names such as build, //sub:build, lint:fix and a-b are unchanged, and args were already passed after --.

Tests: unit tests for rejected and accepted names; clippy clean.

AI-assisted — Tool: Claude Code; model: anthropic/claude-sonnet-5-5; version: 2.1.289.

🤖 Generated with Claude Code


Note

Low Risk
Input validation on the MCP tool path only; valid task names behave as before and the change reduces mistaken or abusive flag injection from MCP clients.

Overview
Hardens the MCP run_task tool so caller-supplied task names cannot be interpreted as mise run CLI flags.

run_task now runs validate_task_name before spawning mise run. Empty names and any name starting with - (e.g. --raw, --cd=/tmp) return INVALID_PARAMS with explicit messages instead of running unintended behavior such as the default task with raw I/O or a different working directory. Legitimate task names (build, //sub:build, lint:fix, etc.) are unchanged; task arguments still go after --.

Unit tests cover rejected flag-like/empty names and accepted normal names.

Reviewed by Cursor Bugbot for commit b87e829. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Bug Fixes
    • Task names that are empty or begin with a hyphen are now rejected before running, preventing them from being treated as command options.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M453E52JHFYKXFA8577D1Y68
@jdx jdx self-assigned this Oct 5, 2026
@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d5064582-e137-4cd8-a00b-58041cd428f3
📥 Commits

Reviewing files that changed from the base of the PR and between 5b57299 and b87e829.

📒 Files selected for processing (1)
  • src/cli/mcp.rs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

The MCP task runner now rejects empty task names and names beginning with a hyphen before it resolves or launches the executable. Tests cover rejected names and accepted task-name forms.

Changes

Task name validation

Layer / File(s) Summary
Task validation and execution
src/cli/mcp.rs
run_task validates the task name before resolving the executable or spawning a child process. The validator returns INVALID_PARAMS for empty names and names beginning with -. Tests cover these cases and accepted task names.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: risu729

Merge Risk: ⚪ Minimal · up to b87e8

Empty and flag-like task names are rejected before execution, while valid task names and arguments retain the existing path. No actionable merge-blocking risk is evident.

Security Architecture Review

Security architecture risk: 🔵 Low · up to b87e8

The change rejects ambiguous task names before execution and preserves the existing path for accepted names. No introduced or worsened security concern was established. Project tasks retain their existing authority to run with the user's permissions; broader execution isolation remains outside the verified scope.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The changed control applies to MCP callers supplying task names. It reduces option-like input reachability without granting new identity, directory, or process authority. Accepted project tasks retain their pre-existing ability to affect resources available to the executing user; this is not an established new exposure.

Trust Boundaries and Controls

  • observed — The new control prevents caller-controlled task strings beginning with a hyphen from being interpreted as mise run options, including options that change execution directory or mode. The existing -- separator continues to distinguish task arguments from CLI options. This is a task-name control, not a restriction on what an authorized project task may execute.

Resilience and Maintainability Implications

  • observed — Rejected requests terminate before acquiring a child process or running-PID guard, so the new rejection path requires no execution rollback. Repeating or concurrently submitting rejected inputs does not reach task execution. Accepted requests retain the existing spawn-error, timeout, wait-error, success, and failure paths, including the existing kill-on-drop setting; descendant-process cleanup guarantees were not independently established.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: rejecting run_task task names that start with a dash.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 1 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium risk] Adds input validation to the task execution handler.

This PR appears safe to merge; no actionable issues were found.

What we checked:

  • Task names cannot become flags: run_task rejects names starting with - before starting the child. Accepted names remain one command argument.

Summary

run_task now rejects empty and dash-prefixed task names with INVALID_PARAMS before starting a child process.

  • Other names and task arguments keep their existing behavior.
  • New unit tests cover rejected names, accepted names, and the error message for --raw.
  • No actionable issues found. Tests were not run during this review.

Reviews (1) · Last reviewed commit: "fix(mcp): reject run_task task names tha..."

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Instruction counts

Nothing was compared, and so nothing was gated. No series appears on both sides: either the base has no measurements recorded, or the two were measured on different runner classes, which are deliberately not comparable — counts shift between machine types by more than a real regression does.

New, nothing to compare against: env on jdx-perf-v1-ubuntu24.04-x64-mise-rust1.97.1-img5263c143, hook-env on jdx-perf-v1-ubuntu24.04-x64-mise-rust1.97.1-img5263c143, ls on jdx-perf-v1-ubuntu24.04-x64-mise-rust1.97.1-img5263c143, registry on jdx-perf-v1-ubuntu24.04-x64-mise-rust1.97.1-img5263c143, startup on jdx-perf-v1-ubuntu24.04-x64-mise-rust1.97.1-img5263c143

Only instruction counts gate. Wall clock is shown for context — on identical hardware it moves 4-20% run to run.

Measured by tak — instruction-counted CLI benchmarks, stored in this repository's git notes.

b87e82916202 vs 5b57299abfaa · measured on the runner, not pushed to the history.

@jdx
jdx merged commit c8b5eb8 into main Oct 5, 2026
51 of 55 checks passed
@jdx
jdx deleted the claude/mise-secrets-m0 branch October 5, 2026 11:15
jdx pushed a commit that referenced this pull request Oct 7, 2026
<!-- entire-trail-link-start -->
https://entire.io/gh/jdx/mise/trails/430
<!-- entire-trail-link-end -->

### 🚀 Features

- **(bootstrap)** add a tool-update service that keeps auto_update tools
current by @jdx in [#14040](#14040)
- **(config)** add global section write targets by @jdx in
[#14018](#14018)
- **(config)** move mise's auto-update settings under self_update.* by
@jdx in [#14038](#14038)
- **(dotfiles)** report notification availability and add notify command
by @jdx in [#14009](#14009)
- **(dotfiles)** add merge entries that own only some keys of a config
file by @jdx in [#14012](#14012)
- **(http)** add headers option for bearer and API-key auth by @jdx in
[#14022](#14022)
- **(install)** add an opt-in identity-based install layout by @jdx in
[#13951](#13951)
- **(install)** keep identity-layout installations in a shorter
directory on Windows by @jdx in
[#13952](#13952)
- **(installs)** list installations and choose the one requests without
a lockfile use by @jdx in
[#13953](#13953)
- **(installs)** move legacy installations into the identity layout by
@jdx in [#13955](#13955)
- **(lock)** preserve shared lockfile entries on request by @jdx in
[#13980](#13980)
- **(npm)** install packages from git repositories by @jdx in
[#14044](#14044)
- **(prune)** add prune.exclude to keep chosen tools from being pruned
by @jdx in [#14030](#14030)
- **(secrets)** add [secrets.fnox] project config and mise secrets ls by
@jdx in [#13967](#13967)
- **(secrets)** add --secrets and --secrets-all to mise run and mise x
by @jdx in [#13975](#13975)
- **(task)** give tasks only the fnox secrets they list by @jdx in
[#13974](#13974)
- **(task)** allow {{ secrets.X }} in task env values by @jdx in
[#13978](#13978)
- **(upgrade)** update global tools before they run with auto_update by
@jdx in [#14026](#14026)
- **(util)** add a comment-preserving YAML merge helper by @jdx in
[#14010](#14010)
- **(util)** add format-aware merge for JSON, TOML, and YAML files by
@jdx in [#14011](#14011)

### 🐛 Bug Fixes

- **(backend)** read a repository's packslip release list once per
command by @jdx in [#13991](#13991)
- **(backend)** only warn about a backend switch when the backend kind
changes by @jdx in [#14032](#14032)
- **(bootstrap)** don't create history state or fail on its lock unless
writing files by @jdx in
[#14029](#14029)
- **(cargo)** serialize rustup state across cargo install fallbacks by
@jdx in [#14042](#14042)
- **(config)** keep global config when a project ignore resolves onto it
via symlink by @jdx in [#14006](#14006)
- **(doctor)** only warn about backend mismatches the registry serves by
@jdx in [#14005](#14005)
- **(dotenv)** leave a value ending in escaped whitespace unquoted by
@jdx in [#13956](#13956)
- **(dotfiles)** explain missing sources in conflicting declaration
errors by @himkt in [#13973](#13973)
- **(dotfiles)** skip legacy link discovery for group entries by @jdx in
[#14023](#14023)
- **(dotnet)** disable lockfile url enforcement for dotnet tool backend
by @james-newell-forge in
[#13971](#13971)
- **(env)** fully redact secrets when redaction values overlap by @jdx
in [#13962](#13962)
- **(github)** log partial attestation verification failures by @jdx in
[#14035](#14035)
- **(github)** warn when attestations are skipped because the Sigstore
trust root is unreachable by @jdx in
[#14036](#14036)
- **(http)** fetch a cached GitHub release once when callers race by
@jdx in [#13990](#13990)
- **(http)** don't retry a 429 whose Retry-After outlasts the backoff by
@jdx in [#14027](#14027)
- **(http)** retry downloads when an HTTP/2 stream reset fails the body
read by @jdx in [#14049](#14049)
- **(install)** switch backends into a new installation, and resolve
CLI-named versions without guessing by @jdx in
[#13957](#13957)
- **(install)** keep a version incomplete until its postinstall hook
succeeds by @jdx in [#14037](#14037)
- **(install)** keep incomplete-install markers out of the cache by @jdx
in [#14051](#14051)
- **(mcp)** reject run_task task names that start with a dash by @jdx in
[#13961](#13961)
- **(oci)** stream large blob uploads in one PATCH by @jdx in
[#14017](#14017)
- **(outdated)** don't bump vendor-only requests like java@temurin by
@jdx in [#14031](#14031)
- **(prune)** keep versions that a running process was started from by
@jdx in [#14020](#14020)
- **(prune)** snapshot what templated tool versions render to in the
identity layout by @jdx in
[#14025](#14025)
- **(pypi)** build uv tool venvs on mise's python by @jdx in
[#14024](#14024)
- **(pypi)** lock from <root>/simple/ for JSON URLs by @deiga in
[#14007](#14007)
- **(python)** create the auto uv venv with mise's python during install
by @halms in [#13981](#13981)
- **(release)** skip the vfox-tiny test fixture when vendoring embedded
plugins by @jdx in [#14047](#14047)
- **(ruby)** keep Gemfile reload watches out of executable hooks by
@DahanItamar in [#13985](#13985)
- **(task)** list monorepo subproject tasks in the mise://tasks MCP
resource by @jdx in [#14053](#14053)
- **(uninstall)** report each version once in a dry run by @jdx in
[#13992](#13992)

### 📚 Documentation

- **(http)** show a package proxy recipe for url_replacements by @jdx in
[#14050](#14050)
- **(readme)** add Star History badges by @jdx in
[#13968](#13968)
- keep code blocks and alert markers out of llms.txt summaries by
@DahanItamar in [#14034](#14034)

### ⚡ Performance

- **(secrets)** read cached fnox secrets from the fnox daemon by @jdx in
[#13979](#13979)

### 🧪 Testing

- **(e2e)** stabilize task timing assertions by @jdx in
[#13977](#13977)
- **(go)** disable minimum_release_age in go install e2e by @jdx in
[#13989](#13989)

### 📦️ Dependency Updates

- lock file maintenance by @renovate[bot] in
[#13963](#13963)
- update github actions by @renovate[bot] in
[#13994](#13994)
- update rust crates by @renovate[bot] in
[#13996](#13996)
- update rust crate nodejs-semver to v7 by @renovate[bot] in
[#13999](#13999)
- update jdx/mise-action action to v5 by @renovate[bot] in
[#13997](#13997)
- update jdx/renovate-config action to v1.0.2 by @renovate[bot] in
[#14003](#14003)
- update dependency usage to latest by @renovate[bot] in
[#14004](#14004)
- update jdx crates to v6.12.1 by @renovate[bot] in
[#14002](#14002)
- update rust crate sigstore-verify to 0.14 by @jdx in
[#14019](#14019)
- update rattler by @renovate[bot] in
[#13998](#13998)
- update rust crate clx to v3.0.4 by @renovate[bot] in
[#14028](#14028)

### 📦 Registry

- update moved plugin references by @jdx in
[#13972](#13972)

### Chore

- **(ci)** update pr-closer to v1.3.0 by @jdx in
[83f3e90](83f3e90)

### Ci

- update pr closer action by @jdx in
[#13970](#13970)
- add manual M4 sandbox pilot by @jdx in
[09e8f8f](09e8f8f)

### Security

- **(env)** keep secrets inherited from a parent mise out of templates,
caches and other tasks by @jdx in
[#13966](#13966)

### New Contributors

- @DahanItamar made their first contribution in
[#14034](#14034)
- @deiga made their first contribution in
[#14007](#14007)
- @james-newell-forge made their first contribution in
[#13971](#13971)

## 📦 Aqua Registry Updates

### New Packages (3)

-
[`editorconfig/editorconfig-core-go`](https://github.com/editorconfig/editorconfig-core-go)
- [`jdx/jactionlint`](https://github.com/jdx/jactionlint)
- [`tontinton/maki`](https://github.com/tontinton/maki)

### Updated Packages (3)

- [`anchore/syft`](https://github.com/anchore/syft)
- [`eksctl-io/eksctl`](https://github.com/eksctl-io/eksctl)
-
[`regclient/regclient/regsync`](https://github.com/regclient/regclient)
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.

1 participant