Skip to content

fix(security): harden MCP client and scanner against untrusted input#7

Merged
appleboy merged 2 commits intomainfrom
fix/security-hardening
Mar 28, 2026
Merged

fix(security): harden MCP client and scanner against untrusted input#7
appleboy merged 2 commits intomainfrom
fix/security-hardening

Conversation

@appleboy
Copy link
Copy Markdown
Member

Summary

  • Critical: Bound io.ReadAll() with LimitReader in HTTP/SSE transports to prevent memory exhaustion DoS from malicious MCP servers
  • Critical: Validate SSE endpoint URLs against base origin using net/url parsing to prevent SSRF attacks
  • Critical: Prevent symlink traversal in skill directory scanning with filepath.EvalSymlinks() and path containment checks
  • High: Parse --control-server-H headers into ControlServerConfig (flag was defined but never wired up)
  • High: Redact query parameters from URLs and sensitive args in all debug log output
  • Medium: Add sync.Mutex to protect stdio stderr slice from data race
  • Medium: Extract shared HTTP error types (ClientError, NonRetryableError, SanitizeBodySnippet) to internal/httperrors/ to eliminate duplication between upload and analysis packages
  • Medium: Expand secret prefix detection from 5 to 18 known API key patterns plus a high-entropy heuristic
  • Medium: Thread configurable --server-timeout through to session.call() instead of hard-coded 30s
  • Medium: Remove unused --mcp-oauth-tokens-path flag (dead code)

Test plan

  • All existing tests pass with race detector (go test -race ./...)
  • New tests for SSE endpoint URL validation (7 cases: relative, absolute same-origin, different origin, different scheme, path traversal, different port)
  • New tests for symlink traversal protection and isWithinBase boundary checks
  • New tests for control server header parsing
  • New tests for URL and arg sanitization
  • New tests for expanded secret prefix detection and entropy heuristic
  • New tests for shared httperrors package
  • make lint passes with 0 issues
  • make build succeeds

🤖 Generated with Claude Code

appleboy and others added 2 commits March 27, 2026 21:47
- Bound io.ReadAll with LimitReader in HTTP and SSE transports to prevent memory exhaustion DoS
- Validate SSE endpoint URLs against base origin to prevent SSRF attacks
- Prevent symlink traversal in skill directory scanning with EvalSymlinks and path containment checks
- Parse --control-server-H headers into ControlServerConfig to fix unused flag
- Redact query parameters from URLs and sensitive args in debug log output
- Add mutex to protect stdio stderr slice from data race
- Extract shared HTTP error types to internal/httperrors to eliminate duplication
- Expand secret prefix detection with 18 known API key patterns and entropy heuristic
- Thread configurable timeout to session.call instead of hard-coded 30 seconds
- Remove unused --mcp-oauth-tokens-path flag

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Export IsPath and RedactedValue from redact package for reuse
- Remove duplicate isPath function from mcpclient/sanitize
- Use redact.RedactedValue instead of hardcoded magic strings
- Pre-lowercase secret prefixes to avoid repeated ToLower in loop
- Cap stderr line accumulation at 10000 to prevent memory exhaustion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@appleboy appleboy merged commit 86645c2 into main Mar 28, 2026
16 checks passed
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