Skip to content

Conversation

@geckosecurity
Copy link
Contributor

Version: 0.7.2
CVSS: 3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Score: 9.1 (Critical)

Description

There are multiple Insecure Direct Object Reference (IDOR) vulnerabilities in the agent plugin management endpoints that allow unauthenticated attackers to access and modify any user's plugin data. The vulnerability exists in four critical endpoints that accept an optional 'user' parameter without any authentication or authorization checks.

The system falls back to a "default" user when no user is specified, and directly passes user-controlled parameters to database queries without validation. This design flaw allows complete bypass of access controls, enabling attackers to view, install, uninstall, and upload plugins under any user's account.

While there are authentication mechanisms in other parts of the codebase using check_api_key dependencies, the agent hub controller endpoints are completely unprotected and accessible by default when api_keys = [] (the default configuration).

Source - Sink Analysis

Source: User-controlled user parameter in HTTP requests to agent hub endpoints

Call Chain:

  1. HTTP POST to /api/v1/agent/my with user parameter
  2. my_agents() function in packages/dbgpt-serve/src/dbgpt_serve/agent/hub/controller.py:88
  3. plugin_hub.get_my_plugin(user) in packages/dbgpt-serve/src/dbgpt_serve/agent/hub/plugin_hub.py:404
  4. my_plugin_dao.get_by_user(user) in packages/dbgpt-serve/src/dbgpt_serve/agent/hub/plugin_hub.py:408
  5. Sink: SQL query with unvalidated user parameter in packages/dbgpt-serve/src/dbgpt_serve/agent/hub/db/my_plugin_db.py:90

Similar flow applies to:

  • /api/v1/agent/installinstall_plugin()get_by_user_and_plugin()
  • /api/v1/agent/uninstalluninstall_plugin()get_by_user_and_plugin()
  • /api/v1/personal/agent/uploadupload_my_plugin() → database insertion with user parameter

Proof of Concept

# View any user's plugins
curl -X POST "http://localhost:5670/api/v1/agent/my?user=admin"

# Install plugin as another user
curl -X POST "http://localhost:5670/api/v1/agent/install?plugin_name=malicious&user=admin"

# Uninstall another user's plugin
curl -X POST "http://localhost:5670/api/v1/agent/uninstall?plugin_name=target&user=admin"

# Upload plugin under any user's account
curl -X POST "http://localhost:5670/api/v1/personal/agent/upload?user=admin" \
  -F "[email protected]"

# Access default user plugins (when user parameter omitted)
curl -X POST "http://localhost:5670/api/v1/agent/my"

Impact

  • Complete bypass of user access controls in plugin management
  • Unauthorized access to any user's plugin data and configurations
  • Ability to install malicious plugins under arbitrary user accounts
  • Ability to uninstall legitimate plugins from any user
  • Upload of malicious code execution payloads under any user context
  • Cross-user data leakage in multi-tenant deployments
  • Potential for privilege escalation through malicious plugin installation

cc: @fangyinc @Aries-ckt

@github-actions github-actions bot added the fix Bug fixes label Jul 7, 2025
def init_app(self, system_app: SystemApp):
system_app.app.include_router(router, prefix="/api", tags=["Agent"])
try:
global_api_keys = system_app.config.get("dbgpt.app.global.api_keys")
Copy link
Collaborator

Choose a reason for hiding this comment

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

hi @geckosecurity global_api_keys variable maybe always None, it seem like ModulePlugin is initialized before the"dbgpt.app.global.api_keys"

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

Labels

fix Bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants