Skip to content

fix(comm): honour the bind host in Host validation, and let e2e CI fail (#89) - #92

Merged
dsiddharth2 merged 1 commit into
Apra-Labs:mainfrom
dsiddharth2:fix/89-e2e-false-green
Nov 4, 2026
Merged

dsiddharth2 merged 1 commit into
Apra-Labs:mainfrom
dsiddharth2:fix/89-e2e-false-green

Conversation

@dsiddharth2

Copy link
Copy Markdown
Collaborator

Fixes #89.

Problem

Three stacked faults, each hiding the next:

  1. Host validation ignored the bind host. comm/express.mjs and mcp/http.mjs called createMcpExpressApp() with no options, so the SDK assumed 127.0.0.1 and accepted only localhost Host headers. An agent bound to 0.0.0.0 (container, VM) refused every request addressed by hostname or IP with 403 Invalid Host, /health included.
  2. The e2e CI step could not fail. $COMPOSE run --rm e2e | tee e2e-vm.log ran without pipefail, so the step took tee's exit code.
  3. The webhook receiver was unreachable. docker compose run does not register the e2e service alias without --use-aliases.

Changes

  • Pass the real bind host to createMcpExpressApp() in the express adapter and the standalone MCP server. Localhost binds keep the strict localhost check; 0.0.0.0 binds rely on the authenticator, as the SDK intends.
  • New optional comm.allowedHosts (or MCP_ALLOWED_HOSTS=a,b): when set, only the listed hostnames are accepted on any bind. Config wins over env; a malformed value fails at startup. Helper in comm/allowed-hosts.mjs.
  • CI: the e2e step runs with shell: bash (-eo pipefail).
  • e2e: run --rm --use-aliases e2e in CI, e2e:vm, e2e:durable and the compose header.
  • docker-compose.e2e.yml sets MCP_ALLOWED_HOSTS: "agent-vm,localhost" so CI exercises the strict path.
  • Docs: "Host header validation" section in docs/mcp-interface.md; comm.host / comm.allowedHosts rows in docs/getting-started.md.

Testing

  • 10 new unit tests (comm-express, host-config, mcp), written first; 8 failed before the fix, all pass now.
  • Full tests/*.test.mjs run: no new failures versus main. The remaining failures are pre-existing on Windows (exec bit, symlinks, packaging, live Fleet); one TTL pool test flaked under full-suite load and passes 5/5 on its own.
  • npm run smoke: 10 pass, 1 skipped.
  • Docker e2e (agent-vm), previously 0/10:
Test Result
health + 5 scenarios + 404 + cancel + 429 backpressure pass
webhook delivers exactly one settled event pass
record survives an agent restart skip (needs E2E_RESTART_CMD)

Totals: 10 pass, 0 fail, 1 skipped.

  • Allowlist probe inside the container: Host: agent-vm → 200, Host: localhost → 200, Host: evil.example → 403 Invalid Host.

Known, not fixed here

npm run e2e:vm / e2e:durable don't run on Windows: npm uses cmd.exe, where ; is not a command separator. This was already the case before this change; it works on Linux/CI, and npm run verify (Wave 0) will replace these scripts.

…il (Apra-Labs#89)

The MCP Express app was built with no options, so the SDK assumed a
127.0.0.1 bind and accepted only localhost Host headers. An agent bound
to 0.0.0.0 in a container or VM refused every request addressed by
hostname or IP with 403 Invalid Host, /health included.

- Pass the real bind host to createMcpExpressApp() in the express
  adapter and the standalone MCP server.
- Add optional comm.allowedHosts / MCP_ALLOWED_HOSTS to restrict the
  accepted Host names on any bind.
- CI: run the e2e step with shell: bash so pipefail stops tee from
  masking a failing suite.
- e2e: run the runner with --use-aliases so the agent can reach the
  webhook receiver at http://e2e:9000.
- e2e compose sets MCP_ALLOWED_HOSTS so CI exercises the strict path.
@dsiddharth2
dsiddharth2 merged commit 7f8f255 into Apra-Labs:main Nov 4, 2026
6 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.

e2e (vm) is 0/10 on main but green: Host validation ignores the bind host, and the CI step masks failures

1 participant