Problem
isTeamScopedView() in admin.js:207 trims team_id before checking emptiness:
function isTeamScopedView() {
const teamId = new URLSearchParams(window.location.search).get("team_id");
return Boolean(teamId && teamId.trim() !== "");
}
But the visibility coercion logic in all 6 edit functions (editTool, editA2AAgent, editResource, editPrompt, editGateway, editServer) checks raw teamId truthiness without trimming:
const effectiveVisibility =
window.ALLOW_PUBLIC_VISIBILITY === false &&
visibility === "public" &&
teamId // ← raw truthiness, no trim
? "team"
: visibility;
The server-side check in _check_public_visibility_allowed (admin.py:1306) also uses raw truthiness:
if not settings.allow_public_visibility and visibility == "public" and team_id:
Impact
With a malformed URL like ?team_id=%20 (whitespace-only):
isTeamScopedView() returns false (trimmed empty string)
- Edit function coercion treats it as team-scoped (
" " is truthy)
applyVisibilityRestrictions does NOT disable the public radio (relies on isTeamScopedView)
- Result: coercion silently changes public→team, but the public radio appears enabled
Not a security issue (server still blocks public visibility submission), but produces confusing UX.
Suggested Fix
Make the edit function coercion checks use isTeamScopedView() instead of raw teamId truthiness. For functions that use a local _teamId variable solely for the coercion check (editResource, editPrompt, editServer), replace it with isTeamScopedView(). For the others, replace just the coercion condition.
Optionally, also normalize on the server side in _check_public_visibility_allowed with team_id and team_id.strip().
References
Problem
isTeamScopedView()inadmin.js:207trimsteam_idbefore checking emptiness:But the visibility coercion logic in all 6 edit functions (
editTool,editA2AAgent,editResource,editPrompt,editGateway,editServer) checks rawteamIdtruthiness without trimming:The server-side check in
_check_public_visibility_allowed(admin.py:1306) also uses raw truthiness:Impact
With a malformed URL like
?team_id=%20(whitespace-only):isTeamScopedView()returnsfalse(trimmed empty string)" "is truthy)applyVisibilityRestrictionsdoes NOT disable the public radio (relies onisTeamScopedView)Not a security issue (server still blocks public visibility submission), but produces confusing UX.
Suggested Fix
Make the edit function coercion checks use
isTeamScopedView()instead of rawteamIdtruthiness. For functions that use a local_teamIdvariable solely for the coercion check (editResource,editPrompt,editServer), replace it withisTeamScopedView(). For the others, replace just the coercion condition.Optionally, also normalize on the server side in
_check_public_visibility_allowedwithteam_id and team_id.strip().References
isTeamScopedView():mcpgateway/static/admin.js:207admin.js:3509(editTool),admin.js:5108(editResource),admin.js:6872(editServer)mcpgateway/admin.py:1293