From 63114bf1cee8f33eb72506a3f8abbf0e752bfbe0 Mon Sep 17 00:00:00 2001 From: Sayak Maity Date: Tue, 3 Feb 2026 18:33:25 -0500 Subject: [PATCH] fix: do not bypass permission grants for agent-created resources When agents create tasks via ACP, the authorization service was incorrectly bypassing the grant() operation due to _bypass() returning True when agent_identity is set. This caused permission records to not be created, resulting in 403 Forbidden errors when users tried to view agent-created tasks from the SGP UI. This fix splits the bypass logic into two methods: - _bypass_check(): Used for check() and list_resources() - bypasses when agent_identity is set OR authorization is disabled (preserves existing agent-to-agent trust behavior) - _bypass_write(): Used for grant() and revoke() - only bypasses when authorization is disabled, NOT when agent_identity is set (ensures permission records are always created) Root cause: Tasks created by agents had no permission records, so when users accessed them via the UI, the permission check failed even though the user had role-based access to the account. --- .../domain/services/authorization_service.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/agentex/src/domain/services/authorization_service.py b/agentex/src/domain/services/authorization_service.py index 8400603..34acb09 100644 --- a/agentex/src/domain/services/authorization_service.py +++ b/agentex/src/domain/services/authorization_service.py @@ -31,18 +31,31 @@ def __init__( self.agent_identity = request.state.agent_identity self.enabled = enabled - def _bypass(self) -> bool: + def _bypass_check(self) -> bool: + """Bypass authorization checks for agent-to-agent calls or when disabled. + + Used for check() and list_resources() operations where we trust agent identity. + """ if self.agent_identity: return True return not self.is_enabled() + def _bypass_write(self) -> bool: + """Bypass authorization writes only when authorization is disabled. + + Used for grant() and revoke() operations. We do NOT bypass these for + agent_identity because permission records must still be created so that + users can access agent-created resources (tasks, etc.) from the UI. + """ + return not self.is_enabled() + def is_enabled(self) -> bool: return self.enabled async def grant( self, resource: AgentexResource, *, commit: bool = True, principal_context=... ) -> None: - if self._bypass(): + if self._bypass_write(): logger.info( f"Authorization bypassed for grant operation on resource {resource}" ) @@ -67,7 +80,7 @@ async def grant( async def revoke( self, resource: AgentexResource, *, commit: bool = True, principal_context=... ) -> None: - if self._bypass(): + if self._bypass_write(): logger.info("Authorization bypassed for revoke operation") return None @@ -98,7 +111,7 @@ async def check( *, principal_context=..., ) -> bool: - if self._bypass(): + if self._bypass_check(): logger.info("Authorization bypassed for check operation") return True @@ -166,7 +179,7 @@ async def list_resources( ) -> Iterable[str] | None: """List resource identifiers for which the current principal has *filter_operation* permission.""" - if self._bypass(): + if self._bypass_check(): logger.info("Authorization bypassed for list_resources operation") return None