fix(mcp): exact-match dangerous flags, stop -c substring false positives#1115
fix(mcp): exact-match dangerous flags, stop -c substring false positives#1115nguyennguyenit wants to merge 1 commit into
Conversation
Previously ValidateArgs flagged any arg containing '-c', '-e', or '-r' as
substrings, blocking legitimate npm package names like 'clickup-cli'. Split
the check: short/long flags now require exact match (or '--flag=value' prefix),
while inline-code patterns ('exec(', '__import__', 'subprocess', etc.) keep
substring semantics.
Closes #1027.
|
Backlog review: merge-candidate. This cleanly fixes #1027 by separating exact dangerous flags from true code-execution substrings, includes regression tests for clickup-cli-style false positives and --flag=value rejection, and go/web checks pass. I closed #1152 as superseded by this cleaner dev-targeted PR. |
clark-cant
left a comment
There was a problem hiding this comment.
PR Review
Verdict: REQUEST CHANGES
Summary
This PR fixes the real false positive from #1027: package names like @nick.bester/clickup-cli should not be rejected just because they contain -c as a substring.
Risk level: medium, because this is security validation for MCP stdio command arguments.
Findings
- [HIGH] internal/mcp/validation.go:103 — short dangerous flags can be bypassed when the option argument is attached to the flag.
The new logic only rejects short flags by exact argument match or flag= form. That fixes the substring false positive, but it also allows forms that many runtimes accept as code-execution flags with attached operands, for example:
- python -cpass / python -c print style attached -c code
- node -e throw style attached -e code
- node -rmodule style attached require preload
Some payloads with parentheses will still be caught later by shellMetaChars, but not all valid code requires those characters. For example, an arg like -cpass has no shell metacharacters and currently passes validation.
Suggested fix: keep the PRs important substring fix, but treat short dangerous options as flags when they appear at the start of an argument too, not anywhere inside it. For example:
- reject exact -c, -e, -r
- reject attached forms beginning with -c, -e, -r when they are intended as short option operands
- continue allowing package names or paths where -c, -e, -r appear later in the string, e.g. @nick.bester/clickup-cli
Please add regression tests for attached short-option bypasses, e.g. -cpass, -ethrow, and -rmodule.
Anti-AI-Slop Check
- Intent clear: yes — fixes a concrete false positive and closes #1027.
- Diff scope justified: yes — small and targeted.
- Refactor justified: not applicable.
- Author explanation needed: no.
Tests / CI
- CI: go ✅, web ✅
- Local targeted check: go test ./internal/mcp -run ValidateArgs ✅
- Test gap: missing negative tests for attached short dangerous flags: -c code, -e code, -r module.
Final Notes
Direction is good, but this validator protects MCP stdio execution. Avoiding substring false positives is right; allowing attached short code-execution flags is too risky to merge as-is.
clark-cant
left a comment
There was a problem hiding this comment.
Maintainer Review — github-maintain
Summary: Fixes false positive in MCP ValidateArgs where package names containing -c, -e, or -r as substrings (e.g. @nick.bester/clickup-cli) were incorrectly rejected as dangerous flags.
Verdict: Approve ✅
Mandatory Gates
| Gate | Result |
|---|---|
| Duplicate / prior implementation | Clear — #1152 attempted the same fix but was closed. This PR's approach (separating flag exact-match from substring-match) is cleaner. |
| Project standards | Clear — follows existing validation patterns, adds regression tests. |
| Strategic necessity | Clear value — unblocks legitimate MCP server packages from being rejected. Closes #1027. |
Risk Level: Low
- 2 files changed, +27/-10 lines
- Clean separation:
dangerousArgFlags(exact match) vsdangerousArgSubstrings(substring match) - Existing dangerous patterns (
exec(,eval(,__import__,child_process,subprocess) retain substring semantics — correct, since these are inline code patterns - 5 new test cases including regression for
clickup-cli,some-experimental-pkg,some-runner-pkg, and--eval=...flag form - CI was green (go + web checks both SUCCESS)
Code Quality
The change is well-structured:
dangerousArgFlagsuses exact match OR--flag=valueprefix — prevents false positives while still catching--eval=process.exit(1)dangerousArgSubstringskeeps the original substring semantics for inline code patterns- Comments explain the rationale clearly
Blocker
mergeStateStatus = DIRTY — branch needs rebase onto current dev. The fix itself is correct and ready to merge once rebased.
@nguyennguyenit could you rebase onto dev? After that this is good to merge.
Posted by github-maintain at $(date -u +'%Y-%m-%dT%H:%M:%SZ')
clark-cant
left a comment
There was a problem hiding this comment.
Approved: clean fix for MCP arg validation false positive. Splits dangerous patterns into exact-match flags vs substring matches, eliminating false positives like clickup-cli matching -c. CI green (+27/-10, 2 files). Low risk.
Note: mergeStateStatus=DIRTY — branch needs rebase onto dev before merge can proceed.
Closes #1027.
clark-cant
left a comment
There was a problem hiding this comment.
Approved — clean fix for #1027. Separates exact-match dangerous flags (-c, -e, -r, --eval, --require, --import) from true code-execution substrings (exec(, eval(, import, child_process, subprocess). Regression tests cover clickup-cli false positive and --flag=value rejection. CI green (go + web). Noted: mergeStateStatus=DIRTY, needs rebase onto dev by author before merge.
clark-cant
left a comment
There was a problem hiding this comment.
Review: fix(mcp): exact-match dangerous flags, stop -c substring false positives
Summary: Splits MCP arg validation into two categories — dangerous flags (exact match or --flag=value prefix) and dangerous code-execution substrings. Fixes false positive where @nick.bester/clickup-cli was rejected because it contained -c as a substring.
Risk level: Low — focused 2-file change (+27/-10), well-scoped to MCP validation.
Mandatory gates:
- Duplicate / prior implementation: clear — no prior fix for #1027
- Project standards: clear — follows existing validation patterns
- Strategic necessity: clear value — fixes broken MCP server configs with package names containing
-c/-e/-rsubstrings
Findings:
- No Critical or Important issues
- Clean separation of flags vs substrings is the correct approach
- Test coverage includes regression cases for the false positives and the
--eval=...prefix form - CI green (go ✅, web ✅)
Verdict: Approve
Posted by /ck:review-pr at 2026-07-16T09:58:00Z
Summary
Closes #1027.
Test plan