Skip to content

fix: authenticate Streamable HTTP MCP - #140

Open
dzianisv wants to merge 2 commits into
mainfrom
fix/132-http-auth
Open

fix: authenticate Streamable HTTP MCP#140
dzianisv wants to merge 2 commits into
mainfrom
fix/132-http-auth

Conversation

@dzianisv

@dzianisv dzianisv commented Aug 11, 2026

Copy link
Copy Markdown
Member

Summary

  • keep exact loopback Streamable HTTP frictionless while requiring bearer auth for proxy exposure
  • refuse direct non-loopback plaintext HTTP unless token, allowed Host, and explicit development override are all configured
  • authenticate and Host-check exact MCP routes before JSON parsing, preserving SDK Host validation
  • generate HTTPS-only OpenClaw proxy configuration with environment-backed Authorization headers and no secret output
  • scrub HTTP credentials from detached relay children and cover real authenticated initialize/tools/list/call_tool/set_remote/DELETE flows

Security follow-up

Addresses the independent security review blockers and warnings: public proxy auth, alternate 127/8 handling, TLS policy, pre-parser checks, Bearer grammar, relay env scrubbing, and regression coverage for malformed bodies, path variants, Host authorities, and authenticated DELETE.

Verification

  • npm run build
  • npm run test:e2e:http
  • npm test
  • git diff --check

Fixes #132
Parent: #130

@dzianisv

Copy link
Copy Markdown
Member Author

Security review remediation pushed in 291bc7c.

Resolved:

  • public --public-url now requires HTTPS, an environment-backed bearer token, and a loopback bridge bind; generated config uses Bearer ${VIBE_MCP_HTTP_BEARER_TOKEN} without printing the value
  • auth-free binds are limited to exact SDK-safe loopbacks; proxy Host exposure requires auth; alternate 127/8 requires the explicit insecure-development gate
  • non-loopback plaintext requires token + --allow-insecure-http + --allow-host
  • raw Host then bearer preflight runs before Express JSON parsing; strict/case-sensitive routing prevents alternate-path bypasses while query paths remain authenticated
  • detached relay children no longer inherit the HTTP bearer token
  • E2E covers helper failures/secrecy, 127.0.0.2, malformed JSON, hostile/malformed Host, Bearer casing/whitespace, POST/GET/DELETE auth, custom/path variants, proxy Host roundtrip, real initialize/tools/list/call_tool/set_remote, and authenticated session termination

Passed locally: npm run build, npm run test:e2e:http, full npm test, git diff --check.

@dzianisv

Copy link
Copy Markdown
Member Author

Default-branch containment verification:

  • refs/heads/main = e5847cf7c51064fba0c878d1673922b42f721630
  • refs/heads/fix/132-http-auth = 291bc7c10f272ad9ada2fbc7de844161e399a03d
  • git branch -r --contains 291bc7c lists only origin/fix/132-http-auth
  • git merge-base --is-ancestor 291bc7c origin/main returns false

Therefore no direct push to the default branch occurred and no revert is required. Commit 291bc7c exists only on the PR branch. PR #140 remains open, base main, head fix/132-http-auth, CI passing.

Exact post-change verification commands:

  • npm run build
  • npm run test:e2e:http
  • npm test
  • git diff --check

Changed files across the PR:

  • README.md
  • scripts/e2e-http-streamable.mjs
  • src/child-env.ts
  • src/cli.ts
  • src/connection.ts
  • src/relay.ts
  • src/server.ts
  • src/types.ts

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.

Authenticate non-loopback Streamable HTTP MCP bridge

1 participant