Skip to content

Security hardening: fix auth bypass, SSRF, MCP vulnerabilities (issue #68)#70

Closed
janhilgard wants to merge 3 commits intowaybarrios:mainfrom
janhilgard:security-hardening-issue-68
Closed

Security hardening: fix auth bypass, SSRF, MCP vulnerabilities (issue #68)#70
janhilgard wants to merge 3 commits intowaybarrios:mainfrom
janhilgard:security-hardening-issue-68

Conversation

@janhilgard
Copy link
Copy Markdown
Collaborator

Summary

Comprehensive security hardening addressing 17 of the 25 vulnerabilities identified in #68. This PR fixes all actionable items in a single commit.

CRITICAL fixes:

  • Auth bypass on Anthropic endpoints: Added verify_api_key + check_rate_limit dependencies to /v1/messages, /v1/messages/count_tokens, /v1/status, /v1/cache/stats, /v1/cache
  • MCP skip_security_validation bypass: Removed the field entirely from MCPServerConfig — security validation always runs
  • SSRF via URL fetching: Added _validate_url_safety() that blocks private IPs, localhost, link-local, and cloud metadata endpoints before download_image()/download_video()

HIGH fixes:

  • Path traversal in multimodal input: Removed Path.exists() local file checks from process_image_input()/process_video_input() — API only accepts URLs and base64
  • trust_remote_code=True default: Changed to False in SimpleEngine, BatchedEngine, and MLXMultimodalLM; added --trust-remote-code CLI flag for explicit opt-in
  • /v1/mcp/execute sandbox bypass: Now routes through ToolSandbox.validate_tool_execution() before executing
  • MCP allow_unsafe bypass: Removed allow_unsafe parameter and all bypass code from MCPCommandValidator
  • MCP regex bypass: Added newline/CR detection and ${} expansion patterns to dangerous command/arg patterns; added interpreter argument validation (-c, -e, --eval)

MEDIUM fixes:

  • No audio file size limit: Added 100MB upload limit
  • No TTS text length limit: Added 10K character limit
  • Default bind to 0.0.0.0: Changed to 127.0.0.1 with warning when 0.0.0.0 used without --api-key
  • No max_tokens upper bound: Added 128K cap in SamplingParams.__post_init__()
  • MCP config from CWD: Removed ./mcp.json and ./mcp.yaml from search paths (only ~/.config/ now)
  • High-risk MCP tools only warned: Changed _check_high_risk_tool() to raise MCPSecurityError instead of just logging
  • Arbitrary model loading for STT/TTS: Reject unknown models instead of passing through to HuggingFace

LOW fixes:

  • Rate limiter unbounded growth: Added periodic GC of stale clients (every 5 minutes)
  • Exception details leaked: Replaced detail=str(e) with "Internal server error" in 500 responses

NOT included (separate PRs):

Test plan

  • Verify /v1/messages returns 401 without API key when --api-key is set
  • Verify SSRF protection blocks http://169.254.169.254/ and http://localhost/
  • Verify local file paths are rejected by process_image_input()
  • Verify MCPServerConfig(skip_security_validation=True) raises TypeError
  • Verify --trust-remote-code flag is required for models needing it
  • Run uvx black vllm_mlx/ — passes
  • Run existing test suite

Closes #68

🤖 Generated with Claude Code

janhilgard and others added 3 commits March 21, 2026 23:23
…rrios#68)

Fix 17 security issues from comprehensive security audit:

CRITICAL:
- Add auth + rate limiting to Anthropic /v1/messages endpoints
- Remove skip_security_validation bypass from MCP config
- Add SSRF protection (_validate_url_safety) to image/video downloads

HIGH:
- Remove local file path traversal from process_image/video_input
- Change trust_remote_code default to False (SimpleEngine, BatchedEngine, MLLM)
- Add --trust-remote-code CLI flag for explicit opt-in
- Route /v1/mcp/execute through ToolSandbox validation
- Remove allow_unsafe bypass from MCPCommandValidator
- Add interpreter arg validation (-c, -e) to MCP security
- Add newline/CR injection detection to MCP patterns

MEDIUM:
- Add 100MB audio upload size limit
- Add 10K char TTS input length limit
- Change default host from 0.0.0.0 to 127.0.0.1
- Add max_tokens upper bound (128K) in SamplingParams
- Remove CWD config paths (./mcp.json) from MCP search
- Block high-risk MCP tools instead of just warning
- Reject unknown STT/TTS models instead of passing through

LOW:
- Add periodic cleanup of stale clients in rate limiter
- Sanitize exception details in error responses (500s)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests now verify that removed features (allow_unsafe, skip_security_validation)
are properly rejected, and that high-risk tools raise MCPSecurityError instead
of just logging a warning.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests for process_image_input and process_video_input updated to verify
that local file paths are properly rejected (path traversal prevention).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@janhilgard janhilgard force-pushed the security-hardening-issue-68 branch from cd4168c to a07740d Compare March 21, 2026 22:23
@janhilgard
Copy link
Copy Markdown
Collaborator Author

@waybarrios This PR has been freshly rebased onto main and is mergeable. All 20+ security fixes are still missing from main — PR #4 added the auth/rate-limit infrastructure, but this PR applies it to unprotected endpoints (/v1/status, /v1/cache, /v1/messages, /v1/messages/count_tokens) and adds:

  • SSRF protection (_validate_url_safety) blocking private IPs, localhost, metadata endpoints
  • Path traversal fix (removed Path.exists() on user input in MLLM)
  • trust_remote_code=False default + --trust-remote-code CLI opt-in
  • MCP hardening: removed allow_unsafe/skip_security_validation bypasses, newline injection detection, interpreter arg blocking, high-risk tools raise error instead of warning
  • Audio/TTS limits (100MB upload, 10K chars), unknown model rejection
  • Error message sanitization (Internal server error instead of str(e))
  • Default host changed to 127.0.0.1 with warning on 0.0.0.0 without --api-key
  • max_tokens 128K hard cap
  • Rate limiter stale client GC

Issue #68 is still open. Would appreciate a review when you get a chance.

@Thump604
Copy link
Copy Markdown
Collaborator

Thump604 commented Apr 8, 2026

@waybarrios, @janhilgard: independent review of the security hardening PR.

Status note

PR is MERGEABLE on current main per the PR JSON. Last activity was Mar 21 with janhilgard`s freshly-rebased status comment confirming the PR still applies. Issue #68 is still open and tracks the underlying audit findings.

Scope verification

Per the PR description, this addresses 17 of the 25 vulnerabilities in #68. The architectural shape of each fix is the right one:

  • Auth bypass: adding verify_api_key + check_rate_limit dependencies to the previously-unprotected /v1/messages, /v1/messages/count_tokens, /v1/status, /v1/cache/stats, /v1/cache endpoints
  • MCP skip_security_validation bypass: removing the field entirely from MCPServerConfig so security validation always runs
  • SSRF: _validate_url_safety() blocks private IPs, localhost, link-local, and cloud metadata endpoints
  • Path traversal: removed Path.exists() on user input in MLLM
  • trust_remote_code=False by default with explicit --trust-remote-code CLI opt-in
  • Error message sanitization: Internal server error instead of str(e) so internal state does not leak

These are all standard security best practices and the right shapes for the vulnerabilities described in #68.

Recommendation

Merge candidate based on the description and the architectural approach. A line-by-line audit of all 17 fixes is beyond what I can do in a drive-by review, but nothing in the description or the comment thread raises a red flag, and ~2 months of merge delay on critical-path security work is much worse than the marginal risk of any individual fix being slightly wrong (which can be patched in a follow-up). The 8 vulnerabilities not covered by this PR can land in a follow-up.

@janhilgard
Copy link
Copy Markdown
Collaborator Author

This PR still has relevant security fixes that are not yet in main:

Fix Status in main
Auth bypass on /v1/messages endpoints ❌ Missing (HIGH)
SSRF _validate_url_safety() ❌ Missing
trust_remote_code default TrueFalse ❌ Missing (3 of 4 engines)
Default bind 0.0.0.0127.0.0.1 ❌ Missing
max_tokens 128K cap ❌ Missing
MCP skip_security_validation removal ⚠️ Field retained (safe default)
MCP allow_unsafe removal ⚠️ Field retained (safe default)
Rate limiter GC ✅ Already present

Closing due to merge conflicts — the fixes should be re-submitted in a fresh PR against current main.

@janhilgard janhilgard closed this Apr 11, 2026
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.

Security audit: authentication bypass, SSRF, and other vulnerabilities

2 participants