Skip to content

fix(server): refuse unparsable allowed-hosts at startup - #125

Merged
plusky merged 2 commits into
mainfrom
fix/issue-117
Aug 18, 2026
Merged

fix(server): refuse unparsable allowed-hosts at startup#125
plusky merged 2 commits into
mainfrom
fix/issue-117

Conversation

@plusky

@plusky plusky commented Aug 18, 2026

Copy link
Copy Markdown
Owner

What

Hardens HTTP Host validation so a typo in --allowed-hosts / MCP_ALLOWED_HOSTS cannot silently brick a deployment.

  • HTTP start emits one info line stating whether Host validation is on or off and, when on, the resolved list verbatim (Host validation: off / Host validation: on; allowed hosts: …).
  • An entry that is not a hostname or host:port (*, a scheme-carrying URL, a;b, encoded commas, zero-width unicode, a space-containing typo) is a startup error, named in the message. rmcp 3.1.2 would otherwise keep validation on and store (or skip) a host no inbound Host matches — deny-all, one 403 at a time.
  • Whitespace is no longer a list separator. a b.example stays one unparsable entry instead of becoming a single-label a plus b.example. Comma-separated lists still work; whitespace around commas is trimmed.
  • MCP_ALLOWED_HOSTS= still reads as unset (validation off).
  • allowed_origins is unchanged. DESIGN.md already records why it has no knob (inherited empty = off); that decision is not reopened.

Why

Three operator-hostile gaps from #104's review, all fail-closed: no startup visibility of the effective Host list, unparsable entries as a silent deny-all, and whitespace splitting manufacturing authorities from typos.

Invariants

  • I9: naming hosts only ever turns validation on (tightening). Unparsable is fail-closed, not fail-open.
  • I12: the startup line is hosts only; tests pin a canary key is absent from the capture.

Verification

cargo fmt --check
cargo clippy --workspace --all-targets -- -D warnings
cargo clippy -p bugwarden --features gen --all-targets -- -D warnings
cargo test --workspace --all-targets --locked
cargo deny check

Man page and completions regenerated (bugwarden-gen). Tests are mutation-proof: deleting the info line or the unparsable refusal fails config.rs / server.rs / env_config.rs / http_transport_wiremock.rs.

Adversarial review (checklist: silent deny-all, whitespace typo, empty-unset, I12, I9, mutation-proof tests) found no bugs.

Closes #117

@plusky plusky added the ai-assisted Authored or substantially written with an AI coding agent label Aug 18, 2026
plusky added 2 commits August 18, 2026 21:14
Host validation could turn on with nothing matchable when
MCP_ALLOWED_HOSTS held a typo rmcp cannot parse as a Host
authority, and nothing logged the effective on/off list. Split
only on commas so a space-containing typo stays one entry,
refuse unparsable authorities at HTTP start, and emit one info
line with the resolved hosts (I9, I12).

Closes #117
The first-cut matcher treated a colon as a port separator, so bare
IPv6 (::1) made the whole list a startup error. That spelling is
rmcp's default loopback entry and matches inbound Host: [::1].
Parse with http::uri::Authority (wrapping a bare IPv6 literal) and
still refuse * / a;b / the #117 typo list.

Also name an unparsable --allowed-hosts list in the man page EXIT
STATUS, matching the README.
@plusky
plusky merged commit 1a3b0e6 into main Aug 18, 2026
13 checks passed
@plusky
plusky deleted the fix/issue-117 branch August 18, 2026 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-assisted Authored or substantially written with an AI coding agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Host-validation hardening: no startup log of effective state, and unparsable entries silently deny all

1 participant