Skip to content

[Bug] Unauthenticated command execution through ReAct shell_interpreter bypasses local-runtime opt-in #3167

Description

@Carbene

Search before asking

  • I had searched in the issues and found no similar issues.

Operating system information

MacOS(M1, M2...)

Python version information

=3.11

DB-GPT version

latest release

Related scenes

  • Chat Data
  • Chat Excel
  • Chat DB
  • Chat Knowledge
  • Model Management
  • Dashboard
  • Plugins

Installation Information

Device information

CPU: M5 with RAM 24G

Models information

None.

What happened

Using a stubbed ReAct model response containing a validshell_interpreter action, I verified that DB-GPT executed the supplied Bashpayload through the local runtime.

The command ran inside the webserver container as the webserver process user.In the tested Docker deployment, this user was root.

Separately, source inspection shows that an HTTP request without the user_idheader is assigned the default administrator identity "001".

What you expected to happen

DB-GPT should enforce the following security invariants:

The ReAct endpoint should reject unauthenticated requests rather than assignthem a mock administrator identity.

A shell-capable tool should not be exposed to unauthenticated orinsufficiently authorized users.

Runtime selection should use the guarded runtime factory and fully respect SANDBOX_ALLOW_LOCAL_RUNTIME.

When local runtime has not been explicitly enabled, shell execution shouldfail closed rather than silently fall back to LocalRuntime.

Security-sensitive shell actions should require an explicit authorizationor confirmation step unless the deployment administrator has deliberatelyconfigured otherwise.

How to reproduce

The PoC is available at:

https://gist.github.com/Carbene/5093aecc49970b35f396aaadec8af030

Before running it, verify the runtime setting in the webserver container:

docker exec <your container name> bash -lc \
  'printf "SANDBOX_ALLOW_LOCAL_RUNTIME=%s\n" \
  "${SANDBOX_ALLOW_LOCAL_RUNTIME-<unset>}"'

Copy the PoC into the webserver container:

docker cp poc.py <your container name>:/app/poc.py

Run it using the Python environment installed in the container:

docker exec <your container name> bash -lc \
  'cd /app && /opt/.uv.venv/bin/python poc.py'

Then the output should be:

PWNED_BY_STUB_REACT_SHELL
/app
uid=0(root) gid=0(root) groups=0(root)
MARKER_CREATED:/tmp/DBGPT_REACT_SHELL_POC_...
RESULT: VULNERABLE_PATH_CONFIRMED

Additional context

About

The ReAct chat endpoint exposes a shell_interpreter tool capable of executingBash commands in the DB-GPT webserver execution environment.

Two issues combine to make this security-sensitive:

POST /api/v1/chat/react-agent accepts requests without an authenticatedidentity. When the user_id HTTP header is absent,get_user_from_headers() returns the default administrator user "001".

The shell tool directly selects a local runtime instead of using the guardedruntime-selection path. As a result, local execution can occur even when theadministrator has not explicitly enabled local runtime throughSANDBOX_ALLOW_LOCAL_RUNTIME.

Once the model emits a valid shell_interpreter ReAct action, the action isparsed and dispatched without a separate authorization or user-confirmationstep. The resulting Bash process runs with the webserver container's workingdirectory, environment, filesystem access, network access, and OS privileges.

The attached PoC uses a deterministic stubbed model response. It thereforedemonstrates the security-relevant execution path after the model has selectedthe shell tool, without depending on the behavior or prompt-injectionsusceptibility of a particular model.

Src-to-Sink Analysis

Unauthenticated POST /api/v1/chat/react-agent
  -> get_user_from_headers() receives no user_id HTTP header
  -> default administrator user "001" is returned
  -> dialogue.user_input becomes AgentMessage content
  -> ReAct agent is built with shell_interpreter in its ToolPack
  -> model may emit Action: shell_interpreter with attacker-influenced input
  -> ReActOutputParser parses the action
  -> ReActAction dispatches it without a separate authorization check
  -> shell_interpreter selects LocalRuntime directly
  -> configured runtime guard/factory is bypassed
  -> LocalSandboxSession writes a Bash script
  -> bash <script> is launched as a subprocess
  -> subprocess inherits the webserver container's environment and privileges

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions