fix(security): harden auth — UUID-first user resolution, weak-password guard, streamable-HTTP team checks - #5872
Open
jonpspri wants to merge 7 commits into
Open
fix(security): harden auth — UUID-first user resolution, weak-password guard, streamable-HTTP team checks#5872jonpspri wants to merge 7 commits into
jonpspri wants to merge 7 commits into
Conversation
…ecks - _get_user_by_email_sync/_get_auth_context_batched_sync: try EmailUser.id first when the sub looks like a UUID, fall back to email; team queries now bind the resolved user.email instead of the raw sub parameter - streamablehttp _auth_jwt: propagate the resolved email into the request user context; require_user_in_db no longer rejects tokens whose is_admin claim is valid - _check_streamable_permission: derive team_id from single-team tokens and set check_any_team for multi-team tokens so team-scoped RBAC roles are evaluated on the streamable-HTTP transport Signed-off-by: Jonathan Springer <jps@s390x.com>
…icy setting - Reject a weak/default BASIC_AUTH_PASSWORD at settings validation when any basic-auth method (Admin UI, API, docs) is enabled outside development - Add PASSWORD_CHECK_SEQUENTIAL_CHARS setting and honor it in the password policy service so operators can disable the sequential-character check - apply_environment_aware_defaults: run as a model_validator(mode='after') so require_strong_secrets is derived after all field values are set Signed-off-by: Jonathan Springer <jps@s390x.com>
… and helm values Signed-off-by: Jonathan Springer <jps@s390x.com>
Add SecurityValidator-sanitized debug/info traces around check_permission and _get_user_roles so RBAC deny/grant paths are diagnosable without leaking unsanitized identity data into logs Signed-off-by: Jonathan Springer <jps@s390x.com>
jonpspri
requested review from
Lang-Akshay,
brian-hussey,
crivetimihai,
ja8zyjits and
msureshkumar88
as code owners
July 25, 2026 09:22
The baseline regen was a detect-secrets hook side effect of the .env.example change and is out of scope for this PR. Signed-off-by: Jonathan Springer <jps@s390x.com>
…t neutral Convert both config-surface additions to 1-for-1 line replacements so baseline-tracked line numbers in .secrets.baseline do not shift and the detect-secrets hook stays green without regenerating the baseline. Signed-off-by: Jonathan Springer <jps@s390x.com>
- Rewrite the obsolete before-validator passthrough test to cover the new model_validator(mode='after') contract (require_strong_secrets derived from environment after fields are set) - Make _make_settings hermetic against runner environments that export basic-auth toggles (CI exports MCPGATEWAY_UI_ENABLED=true, which combined with the new weak basic_auth_password guard broke test_strong_key_passes_in_production) Signed-off-by: Jonathan Springer <jps@s390x.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #5864
Summary
Ports the auth-hardening fixes out of the catch-all PR #5417 into a standalone, reviewable change:
mcpgateway/auth.py):_get_user_by_email_sync()and_get_auth_context_batched_sync()now tryEmailUser.idfirst when thesublooks like a UUID and fall back to email lookup. Team queries (personal team, active memberships) bind the resolveduser.emailinstead of the rawsubparameter, so UUID-sub tokens resolve teams identically to email-form tokens.normalize_token_teams()/resolve_session_teams()remain the single token-scoping policy points.mcpgateway/config.py):validate_security_combinations()now rejects a weak/defaultBASIC_AUTH_PASSWORDwhen any basic-auth method (Admin UI, API, docs) is enabled in a non-development environment. Also adds thePASSWORD_CHECK_SEQUENTIAL_CHARSsetting (honored by the password policy service; exposed in.env.exampleand the Helm chart values) and convertsapply_environment_aware_defaultstomodel_validator(mode="after")sorequire_strong_secretsis derived after all field values are set.mcpgateway/transports/streamablehttp_transport.py):_check_streamable_permission()derivesteam_idfrom single-team tokens and setscheck_any_teamfor multi-team tokens so team-scoped RBAC roles are actually evaluated;require_user_in_dbno longer rejects tokens whoseis_adminclaim is valid; the UUID→email resolution from the batched auth context is propagated into the request user context.mcpgateway/services/permission_service.py): debug/info traces aroundcheck_permissionand_get_user_roles, all identity fields passed throughSecurityValidator.sanitize_log_message.Security notes
require_user_in_db, public-only tokens get no team scope, weak basic-auth password rejected in staging/production but still allowed in development and when no basic-auth method is enabled.PASSWORD_CHECK_SEQUENTIAL_CHARSdefault-true setting.