Repository navigation
fix(httpapi): hold profile-pinned agent tokens to their pin on GET /api/v1/servers - #1684
Conversation
A token created with --profile takes its scope from the profile, so its AllowedServers is usually "*" and the smart-mcp-proxy#1166 filter (visibleServers) listed every configured server to it, while /tools, preflight and the MCP surface were already limited to the pin. Apply the caller's own pin to a bare GET /servers, the same way GET /servers?profile=<own pin> does: rows outside the pin disappear, tool_count counts only tools the pin admits, and stats narrow with the list. Admins and legacy-scoped tokens are unchanged. Fixes smart-mcp-proxy#1682
|
Thanks a lot, @james-crowley! This is a clean, well-scoped fix. Reusing Your scope note was right, too. Other read paths ( |
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Description
Fixes #1682.
A token created with
--profiletakes its scope from the profile, so itsAllowedServersis usually"*". The #1166 gate (visibleServers->CanEnumerateServer) only consultsAllowedServers, so a bareGET /api/v1/serverslisted every configured server to a profile-pinned token, while/tools, preflight and the MCP surface were already held to the pin.This applies the caller's own pin to a bare
GET /servers(no?profile=): it is now equivalent toGET /servers?profile=<the caller's own pin>. Rows outside the pin disappear,tool_countcounts only tools the pin admits, andstatsnarrow with the list (no count oracle). Admins, the tray socket and legacy--serverstokens are unchanged, sincecallerHasProfilePinis false for them.The change is
limitServersToCallerPininview_as.go(reusinglimitServersToProfilewith a pass-through evaluator) and one call in each of the two branches ofhandleGetServers(management service and legacy fallback).Scope note: I only changed
/api/v1/servers. Other REST reads gate oncanSeeServer(AllowedServers), so a pinned token may still see out-of-pin servers there (for example per-server subtree routes). I left those alone because the scope comments inscope_subtree.godescribe the pin as ergonomics rather than the boundary, and that looks like a maintainer decision. Happy to follow up if you want the pin applied tocanSeeServeritself.Testing
Verification:
go test ./internal/httpapi/ ./internal/auth/passes.TestServersBareListHeldToCallerPinruns bothhandleGetServersbranches and fails onmain({"filesystem":1,"github":2,"notion":2}instead of{"github":1}).a,b; profileprof=a): admin lists["a","b"], the--profile proftoken lists["a"], and a legacy--servers atoken lists["a"]. On v0.71.1 the profile token listed both.