Post-merge hardening from the #13 security review: - isInitializeRequestBody now delegates to the SDK isInitializeRequest (same predicate as packages/mcp/http.ts), so a bare {method:'initialize'} with no id/params no longer triggers the side-effecting login() (audit-spam / user_sessions growth) before http.ts 400s it. - Bind the Bearer path to the instance workspace: verifyBearerAccess rejects a token whose payload.workspaceId != the instance workspace (resolved via workspaceRepo.findFirst, consistent with the Basic path); optional param so it's a no-op when unset. - Close the user-enumeration timing oracle in verifyUserCredentials: the missing/disabled branch now runs a bcrypt compare against a module-level dummy hash whose cost (12) matches production saltRounds, so both paths take one equal-cost bcrypt compare; the exact CREDENTIALS_MISMATCH_MESSAGE is preserved. - Document the trusted-proxy requirement for the spoofable per-IP brute-force limiter in .env.example (trustProxy is on; deploy behind a trusted proxy). - Add real-execution coverage for enforceBasicLoginGate (SSO enforced / EE-MFA bundled vs not / user-MFA / workspace-enforced-MFA) instead of stubbing the gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.7 KiB
4.7 KiB