From be55d688e792fc5441dda8975e27e20be727735d Mon Sep 17 00:00:00 2001 From: GareArc Date: Mon, 26 Jan 2026 16:00:43 -0800 Subject: [PATCH] security: fix IDOR and privilege escalation in set_default_provider - Add tenant_id verification to prevent IDOR attacks - Add admin check for enterprise tenant-wide default changes - Preserve non-enterprise behavior (users can set own defaults) --- api/controllers/console/workspace/tool_providers.py | 6 +++++- api/services/tools/builtin_tools_manage_service.py | 11 ++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/api/controllers/console/workspace/tool_providers.py b/api/controllers/console/workspace/tool_providers.py index e9e7b72718..c455232787 100644 --- a/api/controllers/console/workspace/tool_providers.py +++ b/api/controllers/console/workspace/tool_providers.py @@ -825,7 +825,11 @@ class ToolBuiltinProviderSetDefaultApi(Resource): current_user, current_tenant_id = current_account_with_tenant() args = parser_default_cred.parse_args() return BuiltinToolManageService.set_default_provider( - tenant_id=current_tenant_id, user_id=current_user.id, provider=provider, id=args["id"] + tenant_id=current_tenant_id, + user_id=current_user.id, + provider=provider, + id=args["id"], + account=current_user, ) diff --git a/api/services/tools/builtin_tools_manage_service.py b/api/services/tools/builtin_tools_manage_service.py index 7afbae92b0..667cde3d48 100644 --- a/api/services/tools/builtin_tools_manage_service.py +++ b/api/services/tools/builtin_tools_manage_service.py @@ -406,18 +406,23 @@ class BuiltinToolManageService: return {"result": "success"} @staticmethod - def set_default_provider(tenant_id: str, user_id: str, provider: str, id: str): + def set_default_provider(tenant_id: str, user_id: str, provider: str, id: str, account: "Account | None" = None): """ set default provider """ with Session(db.engine) as session: - # get provider - target_provider = session.query(BuiltinToolProvider).filter_by(id=id).first() + # get provider (verify tenant ownership to prevent IDOR) + target_provider = session.query(BuiltinToolProvider).filter_by(id=id, tenant_id=tenant_id).first() if target_provider is None: raise ValueError("provider not found") # clear default provider if dify_config.ENTERPRISE_ENABLED: + # Enterprise: verify admin permission for tenant-wide operation + from models.account import TenantAccountRole + + if account and not TenantAccountRole.is_privileged_role(account.current_role): + raise ValueError("Only workspace admins/owners can set default credentials in enterprise mode") # Enterprise: clear ALL defaults for this provider in the tenant # (regardless of user_id, since enterprise credentials may have different user_id) session.query(BuiltinToolProvider).filter_by(