Skip to content

fix(cli): bring the MCP transport to parity with REST — constant-time auth, failed-auth limiter, body ceiling - #400

Merged
ajianaz merged 1 commit into
developfrom
fix/mcp-http-hardening
Oct 16, 2026
Merged

ajianaz merged 1 commit into
developfrom
fix/mcp-http-hardening

Conversation

@ajianaz

@ajianaz ajianaz commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

What

tole serve --transport mcp was missing hardening the REST transport already has. This closes the gaps found by the cora 0.19.0 agent-reviewer trial and verified against the code.

Why

The serve token is approval authority (see the threat model), so the MCP face must not be the weaker door.

Changes

  • New shared auth module (tole-cli lib): ct_eq, bearer_matches (case-insensitive scheme, RFC 7235) and AuthLimiter (fixed window, 10 failures per minute per IP, swept so memory stays bounded). REST now uses it too (same constants and behaviour; the duplicated local code is removed).
  • mcp_http.rs:
    • the bearer token is compared in constant time (was ==);
    • failed auth is limited per source IP: 429 after 10 failures in a minute, even for the right token until the window rolls over (REST parity);
    • request bodies over 1 MiB are refused with 413: a declared Content-Length before any byte is read, a chunked body while it streams (http_body_util::Limited), so neither is buffered whole. Read errors and timeouts stay 400;
    • a transient accept() error (EMFILE, ECONNABORTED, ...) is logged and the loop continues with a 50 ms pause instead of ending the server and every session;
    • the timeout() around the synchronous auth check (it had no await point, so it never fired) is removed; the header read stays bounded by header_read_timeout.
  • CHANGELOG.

Behaviour changes to know about

  • The MCP bearer scheme is now case-insensitive (bearer works), like REST. It used to require exactly Bearer .
  • Clients with 10 failed attempts in a minute are locked out for the rest of that window.

Testing

  • New real-binary mcp_http_hardening tests: valid request (both scheme spellings), 401 x10 then 429 even with the right token, declared 2 MiB body gives 413, chunked 3 MiB body gives 413. All 4 fail on the old code and pass now (run 3 times).
  • Unit tests for auth (constant-time compare, bearer matching, limiter window/recovery/sweep) and for the bounded body collector (streamed overflow, exact ceiling).
  • REST suites (serve_http_hardening, serve_approvals) pass. Note: serve_http_hardening is already flaky on develop (about 1 run in 6 fails at server start, also without this change); not touched here.
  • fmt, clippy -D warnings, cargo test --workspace and cargo check --no-default-features pass; cora review --staged clean.

Refs the MCP findings from the cora 0.19.0 agent-reviewer scan

… auth, failed-auth limiter, body ceiling, resilient accept
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

🔍 Cora AI Code Review

✅ No issues found. Code looks good!


Review powered by cora-code · BYOK · MIT

@ajianaz
ajianaz merged commit 1b9037a into develop Oct 16, 2026
17 of 18 checks passed
@ajianaz
ajianaz deleted the fix/mcp-http-hardening branch October 16, 2026 08:32
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