Skip to content

Fix CI: patch RUSTSEC-2026-0185/0189, add Host allowlist and first tests - #2

Merged
cpoder merged 2 commits into
mainfrom
fix/ci-security-audit
Jul 27, 2026
Merged

Fix CI: patch RUSTSEC-2026-0185/0189, add Host allowlist and first tests#2
cpoder merged 2 commits into
mainfrom
fix/ci-security-audit

Conversation

@cpoder

@cpoder cpoder commented Jul 27, 2026

Copy link
Copy Markdown
Owner

The Security Audit job has been failing since 26 June. cargo audit flagged two advisories:

Crate Version Advisory Severity
quinn-proto 0.11.14 → 0.11.16 RUSTSEC-2026-0185 (remote memory exhaustion) 7.5
rmcp 1.2.0 → 1.8.0 RUSTSEC-2026-0189 (DNS rebinding) 8.8

Why this isn't just a version bump

RUSTSEC-2026-0189 affects the Streamable HTTP server transport — the one this server uses. Upstream fixes it by validating the inbound Host header against an allowlist that defaults to loopback only.

Since --http binds 0.0.0.0 and the README documents that mode "for MCP gateways", taking the patch as-is would have turned CI green while silently 403-ing every non-localhost deployment.

So the secure default is kept and WM_ALLOWED_HOSTS opts hostnames in. Entries are added to the loopback defaults rather than replacing them, so local health checks keep working once a public hostname is configured:

WM_ALLOWED_HOSTS=mcp.example.com,mcp.example.com:8080
WM_ALLOWED_HOSTS='*'   # disables validation entirely, logs a warning

StreamableHttpServerConfig became #[non_exhaustive] in rmcp 1.4, so config construction moves to the builder API. anyhow 1.0.104 and rand 0.10.2 clear the three remaining "unsound" warnings — cargo audit is now completely clean.

First tests

The crate had no tests at all, so the "Build & Test" job guarded nothing. These cover the two places a silent regression costs most.

Scope filtering. The tests read the tool list from the live router rather than a hand-kept array, so tools added later are covered automatically. The key invariant: every package_* tool keeps the deploy scope. A new match arm naming individual package tools ahead of the generic one drops them out of deploy with nothing failing at startup — this is not hypothetical, it is exactly what #1 currently does. Verified by reintroducing that regression:

package_create lost the "deploy" scope (got ["fsl-develop", "develop"]);
a package_* tool must stay reachable for deployment

Two further invariants catch undocumented scopes and admin tools leaking into develop.

Host allowlist. Merging moves out of run_http into config::resolve_allowed_hosts so it can be tested directly: additive merge, duplicate collapsing, and * disabling validation only as a whole entry (*.example.com is not wildcard syntax and must not switch validation off).

Clippy now runs with --all-targets so test code is linted too — without it CI would not have caught the items_after_test_module violation these tests introduced.

Verification

fmt, clippy --all-targets -D warnings, test (15 passing) and audit all pass locally. Plus a smoke test against the real binary:

Host sent Default With WM_ALLOWED_HOSTS=mcp.example.com
localhost:18080 200 200
mcp.example.com 403 200
evil.example.com 403 403

🤖 Generated with Claude Code

https://claude.ai/code/session_01QLxwTsE7P4RmNskk9LuV9L

cpoder and others added 2 commits July 27, 2026 14:30
cargo audit failed the Security Audit job on two advisories:

- quinn-proto 0.11.14 -> 0.11.16 (RUSTSEC-2026-0185, 7.5, remote memory
  exhaustion)
- rmcp 1.2.0 -> 1.8.0 (RUSTSEC-2026-0189, 8.8, DNS rebinding in the
  Streamable HTTP server transport -- the one this server uses)

rmcp >=1.4 fixes the rebinding hole by validating the inbound Host
header against an allowlist that defaults to loopback only. Since
--http binds 0.0.0.0 and the README documents that mode for MCP
gateways, taking the patch as-is would have turned CI green while
silently 403-ing every non-localhost deployment. WM_ALLOWED_HOSTS adds
hostnames on top of the loopback defaults (additive, so local health
checks keep working); a single '*' disables validation and logs a
warning.

StreamableHttpServerConfig became #[non_exhaustive], so config
construction moves from a struct literal to the builder API.

Also bumps anyhow 1.0.104 and rand 0.10.2, clearing the three remaining
"unsound" warnings -- cargo audit is now completely clean.

Verified: fmt, clippy -D warnings, test and audit all pass, plus a smoke
test confirming loopback and allowlisted hosts return 200 while a
foreign Host gets 403.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLxwTsE7P4RmNskk9LuV9L
The crate had no tests at all, so the "Build & Test" CI job guarded
nothing. These cover the two areas where a silent regression is most
costly: gateway scope filtering and the new Host allowlist.

The scope tests read the tool list from the live router rather than a
hand-kept array, so tools added later are covered without touching them.
The key invariant is that every package_* tool keeps the "deploy" scope
-- a new match arm naming individual package tools ahead of the generic
one silently drops them out of "deploy", and nothing fails at startup.
Verified by reintroducing that exact regression: the test fails with the
offending tool and its resulting scope set. Two further invariants guard
undocumented scopes and admin tools leaking into "develop".

Host-allowlist merging moves out of run_http into config::resolve_allowed_hosts
so it can be tested directly: extra hosts are added to the loopback
defaults rather than replacing them, duplicates collapse, and "*"
disables validation only as a whole entry ("*.example.com" is not
wildcard syntax and must not switch validation off).

Clippy now runs with --all-targets so test code is linted too; without it
CI would not have caught the items_after_test_module violation these
tests introduced.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLxwTsE7P4RmNskk9LuV9L
@cpoder
cpoder merged commit 50c24ae into main Jul 27, 2026
4 checks passed
@cpoder
cpoder deleted the fix/ci-security-audit branch July 27, 2026 13:19
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