fix(rbac): gate integrations routes with RequirePermission (EVO-1956)#19
Merged
Merged
Conversation
Closes the Python processor half of the EVO-1956 RBAC audit (2 HIGH): the bulk integrations endpoint and the 12 provider modules were fully reachable by any authenticated user because none of the handlers carried a RequirePermission gate. - integrations_routes.py bulk endpoint gated with integrations.read - 12 provider modules (github, google-calendar, google-sheets, notion, linear, monday, atlassian, asana, hubspot, paypal, canva, supabase): 82 handlers gated by HTTP verb / operation semantics (read / connect / update / create / disconnect) - OAuth callback_routers intentionally NOT gated (browser redirect from external OAuth provider — carries no CRM bearer by design) - Contract test locks in the invariants: every main-router endpoint gated with resource=integrations, action ∈ allow-list; every callback_router endpoint remains unauthenticated Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Sorry @marcelogorutuba, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
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.
Summary
Closes the Python processor half of the EVO-1956 RBAC audit (2 🔴 HIGH findings). Before this PR, every authenticated user (including the default
agentrole, which lacks adminintegrations.*perms) could reach the bulk integrations endpoint and every provider endpoint in the processor — controllers had noRequirePermissiongate, only the auth middleware ran.integrations_routes.pybulk endpoint gated withintegrations.read/(config), GET/discover-tools, GET/calendars, GET/spreadsheetsintegrations.read/discover, POST/authorization, POST/callbackintegrations.connect/availability(calendar query)integrations.read/events(calendar mutation)integrations.create""(save config)integrations.update""(disconnect)integrations.disconnectcallback_routerendpoints intentionally NOT gated — browser redirect from external OAuth provider (github.com, google, etc.) never carries a CRM bearer; gating them would break the OAuth flow. The 12 callback endpoints remain unauthenticated by design.mcp_integration_base.create_mcp_router()factory (currently 0 callers in the repo) left untouched — per-provider handlers are what's actually wired viamain.py.tests/unit/test_integrations_rbac_gates.pylocks the invariants: (1) every main-router endpoint hasRequirePermission("integrations", <verb>)where<verb>is in the auth-serviceresource_actions_config.rballow-list; (2) everycallback_routerendpoint has no permission gate.Validation
evo-ai-processor-community: python -m pytest tests/unit/test_integrations_rbac_gates.py→ 25/25 passevo-ai-processor-community: python -c "import ast; [ast.parse(open(f).read()) for f in glob.glob('src/api/*_routes.py') + ['src/api/mcp_integration_base.py']]"→ all parse OKChanged Files
src/api/integrations_routes.pysrc/api/github_routes.pysrc/api/google_calendar_routes.pysrc/api/google_sheets_routes.pysrc/api/notion_routes.pysrc/api/linear_routes.pysrc/api/monday_routes.pysrc/api/atlassian_routes.pysrc/api/asana_routes.pysrc/api/hubspot_routes.pysrc/api/paypal_routes.pysrc/api/canva_routes.pysrc/api/supabase_routes.pytests/unit/test_integrations_rbac_gates.py(new)Linked Issue
Notes for Reviewer
ai_folders) will land as separate PRs.integrations.executeisn't seeded on any role inresource_actions_config.rb— my initial default mapping for POST subresources would have 403'd Google Calendar'savailabilityandeventsendpoints for everyone including admins. Fixed pre-commit; the contract test'sALLOWED_ACTIONSallow-list now locks this class of regression.discover_oauth(7 providers use POST →connect, 3 providers use GET →readfor the same semantic operation). Unified all 10 toconnect— same OAuth-flow step, same permission.🤖 Generated with Claude Code