Skip to content

[BugFix] Transaction stream-load follow-up requests (commit/rollback) are not re-authenticated #70947

@andyziye

Description

@andyziye

Bug Description

Severity: CRITICAL
Component: BE HTTP Service / Stream Load
Source file: be/src/http/action/transaction_stream_load.cpp (line 251)

Root cause: Authentication is enforced only on the begin request (via parse_basic_auth). Follow-up commit and rollback requests only match by label/db/table and skip any credential re-check, allowing any caller to hijack or abort another user's transaction.

Concrete failure scenario: An attacker who knows a transaction label can roll back or commit another user's in-flight stream load transaction without supplying any credentials.


Steps to Reproduce

# Step 0: Create table
mysql -h127.0.0.1 -P9030 -uroot -e "
  CREATE DATABASE IF NOT EXISTS test_repro;
  CREATE TABLE IF NOT EXISTS test_repro.t_stream (id INT, name VARCHAR(50))
    DISTRIBUTED BY HASH(id) BUCKETS 1 PROPERTIES ('replication_num' = '1');"

# Step 1: Begin transaction with valid credentials
curl -v -X PUT "http://127.0.0.1:18042/api/transaction/begin" \
  -H "Authorization: Basic cm9vdDo=" \
  -H "db: test_repro" \
  -H "table: t_stream" \
  -H "label: hijack_test_label_001"
# => {"Status":"OK","TxnId":2314,...}

# Step 2: Rollback WITHOUT any credentials (attacker)
curl -v -X PUT "http://127.0.0.1:18042/api/transaction/rollback" \
  -H "db: test_repro" \
  -H "table: t_stream" \
  -H "label: hijack_test_label_001"
# => {"Status":"OK",...}  — rollback succeeded with zero credentials

Actual Behavior

  1. begin with valid auth (root): HTTP 200, Status=OK, TxnId=2314 — transaction created.
  2. rollback with no Authorization header: HTTP 200, Status=OK — transaction successfully aborted.
  3. commit with no credentials: accepted and processed through business logic, rejected only due to missing data — not due to auth failure.
  4. Control — begin with wrong credentials: HTTP 200, Status=ANALYSIS_ERROR, "Access denied for user 'wronguser'" — proves auth IS checked on begin.

Expected Behavior

Follow-up requests (commit, rollback) without valid credentials should be rejected with HTTP 401 or Status=AUTH_ERROR. The server should verify that the caller's credentials match those recorded in the StreamLoadContext at transaction begin.


Verification

Runtime test confirmed that commit and rollback follow-up requests succeed without any Authorization header. A transaction begun with valid credentials (root) was rolled back by a second curl with zero credentials, returning HTTP 200 Status:OK. A separate transaction's commit was accepted and processed through business logic — failing only because no data had been loaded, not due to auth rejection. In contrast, a begin with wrong credentials was immediately rejected. Auth is enforced only on begin (via parse_basic_auth in _begin_transaction) and is entirely absent in commit_transaction and rollback_transaction.

This bug was identified and reproduced by AI-assisted code review.


What type of issue is this:

  • BugFix

Does this entail a change in behavior?

  • Yes, this issue will result in a change in behavior.

Type of change:

  • Interface/UI changes

Checklist

  • Fix needs a regression test
  • Fix may need user documentation update

Test Environment

Tested Version main-4d6435b (MySQL protocol 8.0.33)
Cluster Provided cluster: FE=172.26.95.233:9030, BE=172.26.95.230:8040; 3 BEs alive

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions