Skip to content

fix(security): harden auth surfaces (WS credential, MCP default, non-REST audit)#601

Merged
rmyndharis merged 1 commit into
mainfrom
fix/auth-surface-hardening
Jul 2, 2026
Merged

fix(security): harden auth surfaces (WS credential, MCP default, non-REST audit)#601
rmyndharis merged 1 commit into
mainfrom
fix/auth-surface-hardening

Conversation

@rmyndharis

Copy link
Copy Markdown
Owner

Summary

Auth-surface hardening across the WebSocket, MCP, and audit paths. Contains two behavior changes (⚠️ below) — targeted for a minor release.

Changes

  • ⚠️ WebSocket no longer accepts the API key via query string. The ?apiKey= handshake fallback leaked the credential into proxy/access logs. Only the Socket.IO handshake auth.apiKey field and the X-API-Key header are accepted now. Clients using ?apiKey= must switch (docs updated).
  • ⚠️ MCP defaults to read-only. Write tools are exposed only on an explicit MCP_READONLY=false. Previously an unset MCP_READONLY defaulted to read-write, silently exposing state-changing tools (send messages, group ops) the moment MCP_ENABLED was on. Set MCP_READONLY=false to keep the old behavior (docs updated).
  • Audit rejected WebSocket auth attempts (missing and invalid key) with the same API_KEY_AUTH_FAILED event the REST guard emits, so probing over the WS surface leaves a forensic trail.
  • Role-coverage test locking that the ADMIN-only integration provisioning / redrive controllers are guarded server-side — the dashboard's client role is cosmetic UX only.

Verification

npm run build ✓ · npm run lint ✓ · npm test ✓ (1894/1894, +8). New tests: WS ignores a query-string key, WS audits a rejected attempt, MCP read-only secure default resolution, and admin controllers require the ADMIN role.

Follow-up

Auditing MCP and Bull-Board auth failures (raw-Express surfaces) is left as a separate change.

…REST audit)

- Stop accepting the WebSocket API key from the query string — it leaks the credential into proxy/
  access logs. Only the Socket.IO handshake auth field and the X-API-Key header are accepted now.
  (Behavior change: clients using ?apiKey= must switch to auth.apiKey or the header.)
- Default the MCP server to READ-ONLY: write tools are exposed only on an explicit MCP_READONLY=false.
  Previously an unset MCP_READONLY defaulted to read-write, silently exposing state-changing tools the
  moment MCP_ENABLED was on. (Behavior change: set MCP_READONLY=false to keep write tools.)
- Audit rejected WebSocket auth attempts (missing + invalid key) with the same API_KEY_AUTH_FAILED
  event the REST guard emits, so credential probing over the WS surface leaves a forensic trail.
- Add a server-side role-coverage test locking that the ADMIN-only integration surfaces are guarded
  server-side (the dashboard role is cosmetic UX only).

Docs updated for both behavior changes.
@rmyndharis rmyndharis merged commit 7b5a26f into main Jul 2, 2026
3 checks passed
@rmyndharis rmyndharis deleted the fix/auth-surface-hardening branch July 2, 2026 14:38
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