Skip to content

Conversation

@GareArc
Copy link
Contributor

@GareArc GareArc commented Jan 26, 2026

Summary

  • Fixes EE-1511: When setting a new default tool credential in enterprise mode, properly clears ALL existing defaults for that provider in the tenant

Problem

In enterprise mode, credentials synced from global have a different user_id than locally-created credentials. The existing code only cleared defaults for credentials with the same user_id, resulting in multiple credentials having is_default=true simultaneously.

This caused the credential usage check to incorrectly show workflows as "using" a credential that was no longer the effective default.

Solution

  • Enterprise mode: Clear all is_default=true for the provider in the tenant (regardless of user_id)
  • Non-enterprise mode: Preserve original behavior (only clear defaults for current user)

Related

  • Companion PR in enterprise repo handles detecting default credential usage in workflows

… only)

When setting a new default credential in enterprise mode, the code was
only clearing is_default for credentials matching the current user_id.
This caused issues when:
1. Enterprise credential A (synced with system user_id) was default
2. User sets local credential B as default
3. A still had is_default=true (different user_id)
4. Both A and B were considered defaults

The fix removes user_id from the filter only for enterprise deployments,
since enterprise credentials may have different user_id than local ones.
Non-enterprise behavior is unchanged to avoid breaking existing setups.

Fixes EE-1511
@GareArc GareArc requested a review from QuantumGhost as a code owner January 26, 2026 23:42
Copilot AI review requested due to automatic review settings January 26, 2026 23:42
@dosubot dosubot bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Jan 26, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @GareArc, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical bug in enterprise mode where setting a new default tool credential could fail to properly clear all previous defaults for the same provider. The issue stemmed from user_id discrepancies between locally created and globally synced credentials. The changes introduce conditional logic to ensure that in enterprise environments, all existing defaults for a provider within a tenant are cleared, preventing multiple credentials from being marked as default and ensuring accurate credential usage tracking.

Highlights

  • Enterprise Mode Default Credential Clearing: Modified the set_default_provider function to correctly clear all existing default tool credentials for a given provider within a tenant when in enterprise mode, irrespective of the user_id. This resolves an issue where credentials synced from global had different user_ids, preventing proper default clearing.
  • Non-Enterprise Mode Behavior: Preserved the original behavior for non-enterprise mode, where default credentials are only cleared for the current user.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses the issue of multiple default tool credentials in enterprise mode by introducing conditional logic to clear all existing defaults for a given provider within a tenant when dify_config.ENTERPRISE_ENABLED is true. However, the set_default_provider function introduces an IDOR vulnerability due to a missing tenant-scoping check when fetching the target provider by ID. Furthermore, the new Enterprise logic allows any user to modify tenant-wide settings without administrative authorization.

- 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)
@dosubot dosubot bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:S This PR changes 10-29 lines, ignoring generated files. labels Jan 27, 2026
@GareArc
Copy link
Contributor Author

GareArc commented Jan 27, 2026

@gemini-code-assist review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request aims to address the issue of incorrect default tool credential clearing in enterprise mode (EE-1511) by differentiating behavior between enterprise and non-enterprise modes and ensuring all existing defaults for a provider within a tenant are cleared. It also includes crucial security enhancements, such as verifying tenant ownership and administrative permission checks. While it fixes an IDOR vulnerability in set_default_provider, a critical logic flaw remains: the provider name from the request is not validated against the credential's provider attribute. This oversight could allow users to bypass the intended clearing logic, leading to multiple default credentials for a single provider. Additionally, the type hinting for the Account model is a good improvement for code clarity.

Comment on lines +427 to +428
if account and not TenantAccountRole.is_privileged_role(account.current_role):
raise ValueError("Only workspace admins/owners can set default credentials in enterprise mode")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The permission check if account and not TenantAccountRole.is_privileged_role(account.current_role): is a high-priority security measure. It correctly restricts the ability to set tenant-wide default credentials to only privileged roles (admins/owners) in enterprise mode, preventing unauthorized changes.

# 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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The set_default_provider method currently lacks validation to ensure the provider name from the request matches the provider attribute of the credential being updated. This logic flaw could allow an attacker to bypass the intended clearing mechanism and create multiple default credentials for a single provider, leading to unpredictable behavior. While the inclusion of tenant_id=tenant_id correctly prevents IDOR vulnerabilities, the provider validation is still crucial for maintaining data integrity and preventing unintended credential assignments.

            # get provider (verify tenant ownership and provider match to prevent IDOR and logic flaws)
            target_provider = session.query(BuiltinToolProvider).filter_by(id=id, tenant_id=tenant_id, provider=provider).first()

Comment on lines +431 to +433
session.query(BuiltinToolProvider).filter_by(
tenant_id=tenant_id, provider=provider, is_default=True
).update({"is_default": False})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This change correctly implements the core logic for enterprise mode, clearing all is_default=True flags for the specified provider within the tenant. This directly resolves the problem described in EE-1511, where credentials synced from global might have different user_ids, leading to multiple active defaults.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants