[Security] HITL tool-confirmation endpoints (`/pending-confirms`, `/confirm`) have no authentication — unauthenticated approval of arbitrary tool executions
Summary
DB-GPT's human-in-the-loop tool-confirmation flow exposes two unauthenticated HTTP endpoints: GET {prefix}/pending-confirms returns the full pending-confirmation registry (confirm_id, tool_name, args summary), and POST {prefix}/confirm resolves (approves/rejects) any pending tool execution. Neither route carries any auth dependency — the router is instantiated as APIRouter() with no dependencies, unlike other API routes that use Depends(check_api_key). An attacker with network access to the service can list pending confirmations and approve them, executing tools with the user's privileges: the approval gate is fully bypassed.
Affected version
main@ca9f014 (2026-09-16, current HEAD at time of reporting; includes the latest release).
Vulnerable code path
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tools/execute_tool.py:35-55—should_confirmhit → UUIDconfirm_idgenerated → registered in module-level_PENDING_CONFIRMATIONS.packages/dbgpt-serve/src/dbgpt_serve/connector/api/endpoints.py:24—router = APIRouter()with no auth dependencies.endpoints.py:169-173—@router.get("/pending-confirms")returns the full pending registry (confirm_id, tool_name, args summary). No auth dependency.endpoints.py:176-196—@router.post("/confirm")accepts{"confirm_id": "...", "approved": true}and callsregistry.resolve(). No auth dependency.- Contrast:
packages/dbgpt-app/src/dbgpt_app/openapi/api_v2.py:71— chat completion routes useDepends(check_api_key).
Secondary defect (same flow, fail-open)
The confirmation block around execute_tool.py:26-68 wraps registry/assembly errors in except Exception: pass and proceeds to execute the tool without any confirmation — two internal failure classes (registry directory error, component assembly error) silently skip the approval gate (fail-open). A same-shaped pattern exists in packages/dbgpt-app/src/dbgpt_app/openapi/agentic_data_api.py:1898-1964.
Attack chain
- Agent proposes a tool call → confirmation triggers,
confirm_idcreated. - Attacker:
GET {prefix}/pending-confirms(unauthenticated) →confirm_id+ tool_name + args. - Attacker:
POST {prefix}/confirmwith{"confirm_id": "...", "approved": true}→ approval recorded. - Tool executes with the user's privileges — approval gate bypassed.
Impact
- Information disclosure: full parameters of pending tool calls (may include SQL, connection strings, credentials) — CWE-200.
- Privilege escalation: unauthenticated approval of arbitrary pending tool executions — CWE-306.
- Combined with prompt injection: complete remote code execution chain.
CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N (deployments are often network-restricted, but no authentication is required at all).
Suggested fix
Add Depends(check_api_key) (or an equivalent auth dependency) to both /pending-confirms and /confirm, aligning with the rest of the API surface; additionally bind confirm resolution to the originating session/user; change the confirmation-block error handling to fail-closed (abort execution on registry/assembly errors).
Discoverer
Chengzhi Yi (GitHub @Tardfyou) — contact: [email protected]
An offline PoC is available (loads the real confirmation module via importlib; scenarios A/B/C: control guard works, approve-by-id executes, two fail-open paths execute with zero confirmation; exit=0).
Source: eosphoros-ai/DB-GPT